All of lore.kernel.org
 help / color / mirror / Atom feed
* LPC32XX architecture files (updated v3)
@ 2010-02-09  0:11 wellsk40 at gmail.com
  2010-02-09  0:11 ` [PATCH 01/14] ARM: LPC32XX: Initial architecture header files wellsk40 at gmail.com
                   ` (13 more replies)
  0 siblings, 14 replies; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset is the third release of the LPC32xx arch files
with many applicable review comments incorporated. Thank you
everyone that helped review and improve this release.

Changes from previous release to v3 (02/08/2010)

Removed __initdata tag from clock lookup array.
Removed <mach/irqs.h> include from irq entry macro.
Added LPC32XX identifier to device specific names for register
	addresses, bitfields, and other macros
Added LPC32XX identifier to device specific IRQ names
Changes to suspend.S to make it more readable
Changed register addresses and macros to return a virtual address
	via io_p2v of void __iomem * type. Previous types in the
	code that uses a different type now use void __iomem *.
	This makes the code less busy and fixes many sparse
	warnings. Most io_p2v() use in the code has been removed.
_readl/_writel functions use the correct type now without the use
	of __force.
_readl/_writel function arguments all use the direct virtual
	address or an indiced address (for devices that share
	register sets such as timers and UARTs).
Some minor tweaks for sparse warnings
Remove GENERIC_GPIO from arch/arm/Kconfig for mach-LPC32xx
Updated phy3250_defconfig file
The platform Kconfig.plat file was removed.
Arch Kconfig was reduced just the serial port selections.
Added mutex instead of local_irq..() for clock locks.
Revised clock_get_rate code. All clock functions have a get_rate
	callback now instead of just LCD and MCI. Changed the way
	the rate fetch loop was handled.
Switches to abs() and removed clkpwr_abs for clock driver
	functions.
Simplified clock PLL rate config logic.
Fixed USB PLL enable with correct timeout.
Global fixes for all GPL license headers - remove wrong address.
Changed I2C naming to start at '1' instead of '0' to match
	hardware convention.
Added IRAM size autodetect function.
Removed printascii() use in arch file.
Fixed multi-line comments.
Moved some register macros used just in GPIO driver to the
	GPIO driver from platform.h
Added GPIO pin to bit mapping macros
Fixed some names "na" in GPIO name array to NULL.
Expanded a few GPIO driver comments to help explain the more
	wierd mappings better.
Revised debug and uncompress macros to just use the serial port
	UART5 for the output (used on Phytec board).
Revised interrupt handler and entry macro to use chained
	interrupt handlers for SIC1 and SIC2.
Fixed several CLKPWR bit and IRQ macro names that could cause
	confusion with GPI names and the LPC32XX User's guide
Changed VMALLOC_END to 0xF0000000 from PAGE_OFFSET+0x10000000
Added support for set_irq_wake in the interrupt driver with the
	supported wakeup sources. Activation level for GPIO
	events is inherited from the GPIO interrupt config.
The level handlers are used for hardware based level and edge
	interrupts. Thsi is ok for this controller.
Interrupt driver edge/level type logic reduction
FIQ interrupts are no longer enabled by default in the MIC
Changed all readl/writel calls to __raw_readl/__raw_writel.
Removed support for Phytec board variations. This will only
	effect very eaarly LCD based boards. Due to the very
	limited number of boards out there, this really is
	not needed.
Remove board specific code and associated config option for
	setting IRAM as the video frame buffer
Moved IRDA enable/disable from the serial setup code to the
	board specific init code.
Removed event setup code in board init, replaced with
	set_irq_wake functionality now
CPU suspend removed, mem suspend only supported
Allocation and dealloc of temporary storage for IRAM data used
	for suspend is no longer GFP_ATOMIC. Code will only
	alloc when needed and free on completion.
Removed the pm_event driver, replaced (in part) with the
	set_irq_wake support. Events not supported by the
	set_irq_wake functionality need to be configured in the
	board specific init code.
Changed some config names and descriptions for serial port
	setup in KConfig and the serial init code.
Const modifier added to GPIO names

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

* [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-09  9:31   ` Uwe Kleine-König
  2010-02-09  0:11 ` [PATCH 02/14] ARM: LPC32XX: Debug and IRQ macros wellsk40 at gmail.com
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

Initial header files for the LPC32XX architecture

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 arch/arm/mach-lpc32xx/include/mach/board.h      |   23 +
 arch/arm/mach-lpc32xx/include/mach/clkdev.h     |   25 +
 arch/arm/mach-lpc32xx/include/mach/gpio.h       |   74 +++
 arch/arm/mach-lpc32xx/include/mach/hardware.h   |   34 ++
 arch/arm/mach-lpc32xx/include/mach/i2c.h        |   63 ++
 arch/arm/mach-lpc32xx/include/mach/io.h         |   27 +
 arch/arm/mach-lpc32xx/include/mach/irqs.h       |  114 ++++
 arch/arm/mach-lpc32xx/include/mach/memory.h     |   28 +
 arch/arm/mach-lpc32xx/include/mach/platform.h   |  697 +++++++++++++++++++++++
 arch/arm/mach-lpc32xx/include/mach/system.h     |   52 ++
 arch/arm/mach-lpc32xx/include/mach/timex.h      |   29 +
 arch/arm/mach-lpc32xx/include/mach/uncompress.h |   63 ++
 arch/arm/mach-lpc32xx/include/mach/vmalloc.h    |   24 +
 13 files changed, 1253 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-lpc32xx/include/mach/board.h b/arch/arm/mach-lpc32xx/include/mach/board.h
new file mode 100644
index 0000000..30424bc
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/board.h
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/board.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+#ifndef __ASM_ARCH_BOARD_H
+#define __ASM_ARCH_BOARD_H
+
+#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/clkdev.h b/arch/arm/mach-lpc32xx/include/mach/clkdev.h
new file mode 100644
index 0000000..9bf0637
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/clkdev.h
@@ -0,0 +1,25 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/clkdev.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_CLKDEV_H
+#define __ASM_ARCH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/gpio.h b/arch/arm/mach-lpc32xx/include/mach/gpio.h
new file mode 100644
index 0000000..67d03da
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/gpio.h
@@ -0,0 +1,74 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/gpio.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
+
+#include <asm-generic/gpio.h>
+
+/*
+ * Note!
+ * Muxed GP pins need to be setup to the GP state in the board level
+ * code prior to using this driver.
+ * GPI pins : 28xP3 group
+ * GPO pins : 24xP3 group
+ * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group
+ */
+
+#define LPC32XX_GPIO_P0_MAX 8
+#define LPC32XX_GPIO_P1_MAX 24
+#define LPC32XX_GPIO_P2_MAX 13
+#define LPC32XX_GPIO_P3_MAX 6
+#define LPC32XX_GPI_P3_MAX 28
+#define LPC32XX_GPO_P3_MAX 24
+
+#define LPC32XX_GPIO_P0_GRP 0
+#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
+#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
+#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
+#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
+#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
+
+/*
+ * A specific GPIO can be selected with this macro
+ * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
+ * See the LPC32x0 User's guide for GPIO group numbers
+ */
+#define LPC32XX_GPIO(x, y) ((x) + (y))
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	__gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+	return __gpio_cansleep(gpio);
+}
+
+static inline int gpio_to_irq(unsigned gpio)
+{
+	return __gpio_to_irq(gpio);
+}
+
+#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/hardware.h b/arch/arm/mach-lpc32xx/include/mach/hardware.h
new file mode 100644
index 0000000..33e1dde
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/hardware.h
@@ -0,0 +1,34 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/hardware.h
+ *
+ * Copyright (c) 2005 MontaVista Software, Inc. <source@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+/*
+ * Start of virtual addresses for IO devices
+ */
+#define IO_BASE		0xF0000000
+
+/*
+ * This macro relies on fact that for all HW i/o addresses bits 20-23 are 0
+ */
+#define IO_ADDRESS(x)	(((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) |\
+			 IO_BASE)
+
+#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
+#define io_v2p(x)	((((x) & 0x0ff00000) << 4) | ((x) & 0x000fffff))
+
+#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/i2c.h b/arch/arm/mach-lpc32xx/include/mach/i2c.h
new file mode 100644
index 0000000..a2d810b
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/i2c.h
@@ -0,0 +1,63 @@
+/*
+ * PNX4008-specific tweaks for I2C IP3204 block
+ *
+ * Author: Vitaly Wool <vwool@ru.mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASM_ARCH_I2C_H__
+#define __ASM_ARCH_I2C_H__
+
+enum {
+	mstatus_tdi = 0x00000001,
+	mstatus_afi = 0x00000002,
+	mstatus_nai = 0x00000004,
+	mstatus_drmi = 0x00000008,
+	mstatus_active = 0x00000020,
+	mstatus_scl = 0x00000040,
+	mstatus_sda = 0x00000080,
+	mstatus_rff = 0x00000100,
+	mstatus_rfe = 0x00000200,
+	mstatus_tff = 0x00000400,
+	mstatus_tfe = 0x00000800,
+};
+
+enum {
+	mcntrl_tdie = 0x00000001,
+	mcntrl_afie = 0x00000002,
+	mcntrl_naie = 0x00000004,
+	mcntrl_drmie = 0x00000008,
+	mcntrl_daie = 0x00000020,
+	mcntrl_rffie = 0x00000040,
+	mcntrl_tffie = 0x00000080,
+	mcntrl_reset = 0x00000100,
+	mcntrl_cdbmode = 0x00000400,
+};
+
+enum {
+	rw_bit = 1 << 0,
+	start_bit = 1 << 8,
+	stop_bit = 1 << 9,
+};
+
+#define I2C_REG_RX(a)	((a)->ioaddr)		/* Rx FIFO reg (RO) */
+#define I2C_REG_TX(a)	((a)->ioaddr)		/* Tx FIFO reg (WO) */
+#define I2C_REG_STS(a)	((a)->ioaddr + 0x04)	/* Status reg (RO) */
+#define I2C_REG_CTL(a)	((a)->ioaddr + 0x08)	/* Ctl reg */
+#define I2C_REG_CKL(a)	((a)->ioaddr + 0x0c)	/* Clock divider low */
+#define I2C_REG_CKH(a)	((a)->ioaddr + 0x10)	/* Clock divider high */
+#define I2C_REG_ADR(a)	((a)->ioaddr + 0x14)	/* I2C address */
+#define I2C_REG_RFL(a)	((a)->ioaddr + 0x18)	/* Rx FIFO level (RO) */
+#define I2C_REG_TFL(a)	((a)->ioaddr + 0x1c)	/* Tx FIFO level (RO) */
+#define I2C_REG_RXB(a)	((a)->ioaddr + 0x20)	/* Num of bytes Rx-ed (RO) */
+#define I2C_REG_TXB(a)	((a)->ioaddr + 0x24)	/* Num of bytes Tx-ed (RO) */
+#define I2C_REG_TXS(a)	((a)->ioaddr + 0x28)	/* Tx slave FIFO (RO) */
+#define I2C_REG_STFL(a)	((a)->ioaddr + 0x2c)	/* Tx slave FIFO level (RO) */
+
+#define I2C_CHIP_NAME		"PNX4008-I2C"
+
+#endif				/* __ASM_ARCH_I2C_H___ */
diff --git a/arch/arm/mach-lpc32xx/include/mach/io.h b/arch/arm/mach-lpc32xx/include/mach/io.h
new file mode 100644
index 0000000..9b59ab5
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/io.h
@@ -0,0 +1,27 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/io.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT	0xffffffff
+
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/irqs.h b/arch/arm/mach-lpc32xx/include/mach/irqs.h
new file mode 100644
index 0000000..7a78057
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/irqs.h
@@ -0,0 +1,114 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/irqs.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARM_ARCH_IRQS_H
+#define __ASM_ARM_ARCH_IRQS_H
+
+/*
+ * MIC interrupts
+ */
+#define IRQ_LPC32XX_SUB1IRQ		0
+#define IRQ_LPC32XX_SUB2IRQ		1
+#define IRQ_LPC32XX_PWM3		3
+#define IRQ_LPC32XX_PWM4		4
+#define IRQ_LPC32XX_HSTIMER		5
+#define IRQ_LPC32XX_WATCH		6
+#define IRQ_LPC32XX_UART_IIR3		7
+#define IRQ_LPC32XX_UART_IIR4		8
+#define IRQ_LPC32XX_UART_IIR5		9
+#define IRQ_LPC32XX_UART_IIR6		10
+#define IRQ_LPC32XX_FLASH		11
+#define IRQ_LPC32XX_SD1			13
+#define IRQ_LPC32XX_LCD			14
+#define IRQ_LPC32XX_SD0			15
+#define IRQ_LPC32XX_TIMER0		16
+#define IRQ_LPC32XX_TIMER1		17
+#define IRQ_LPC32XX_TIMER2		18
+#define IRQ_LPC32XX_TIMER3		19
+#define IRQ_LPC32XX_SSP0		20
+#define IRQ_LPC32XX_SSP1		21
+#define IRQ_LPC32XX_I2S0		22
+#define IRQ_LPC32XX_I2S1		23
+#define IRQ_LPC32XX_UART_IIR7		24
+#define IRQ_LPC32XX_UART_IIR2		25
+#define IRQ_LPC32XX_UART_IIR1		26
+#define IRQ_LPC32XX_MSTIMER		27
+#define IRQ_LPC32XX_DMA			28
+#define IRQ_LPC32XX_ETHERNET		29
+#define IRQ_LPC32XX_SUB1FIQ		30
+#define IRQ_LPC32XX_SUB2FIQ		31
+
+/*
+ * SIC1 interrupts start at offset 32
+ */
+#define IRQ_LPC32XX_JTAG_COMM_TX	(32 + 1)
+#define IRQ_LPC32XX_JTAG_COMM_RX	(32 + 2)
+#define IRQ_LPC32XX_GPI_11		(32 + 4)
+#define IRQ_LPC32XX_TS_P		(32 + 6)
+#define IRQ_LPC32XX_TS_IRQ		(32 + 7)
+#define IRQ_LPC32XX_TS_AUX		(32 + 8)
+#define IRQ_LPC32XX_SPI2		(32 + 12)
+#define IRQ_LPC32XX_PLLUSB		(32 + 13)
+#define IRQ_LPC32XX_PLLHCLK		(32 + 14)
+#define IRQ_LPC32XX_PLL397		(32 + 17)
+#define IRQ_LPC32XX_I2C_2		(32 + 18)
+#define IRQ_LPC32XX_I2C_1		(32 + 19)
+#define IRQ_LPC32XX_RTC			(32 + 20)
+#define IRQ_LPC32XX_KEY			(32 + 22)
+#define IRQ_LPC32XX_SPI1		(32 + 23)
+#define IRQ_LPC32XX_SW			(32 + 24)
+#define IRQ_LPC32XX_USB_OTG_TIMER	(32 + 25)
+#define IRQ_LPC32XX_USB_OTG_ATX		(32 + 26)
+#define IRQ_LPC32XX_USB_HOST		(32 + 27)
+#define IRQ_LPC32XX_USB_DEV_DMA		(32 + 28)
+#define IRQ_LPC32XX_USB_DEV_LP		(32 + 29)
+#define IRQ_LPC32XX_USB_DEV_HP		(32 + 30)
+#define IRQ_LPC32XX_USB_I2C		(32 + 31)
+
+/*
+ * SIC2 interrupts start at offset 64
+ */
+#define IRQ_LPC32XX_GPIO_00		(64 + 0)
+#define IRQ_LPC32XX_GPIO_01		(64 + 1)
+#define IRQ_LPC32XX_GPIO_02		(64 + 2)
+#define IRQ_LPC32XX_GPIO_03		(64 + 3)
+#define IRQ_LPC32XX_GPIO_04		(64 + 4)
+#define IRQ_LPC32XX_GPIO_05		(64 + 5)
+#define IRQ_LPC32XX_SPI2_DATAIN		(64 + 6)
+#define IRQ_LPC32XX_U2_HCTS		(64 + 7)
+#define IRQ_LPC32XX_P0_P1_IRQ		(64 + 8)
+#define IRQ_LPC32XX_GPI_08		(64 + 9)
+#define IRQ_LPC32XX_GPI_09		(64 + 10)
+#define IRQ_LPC32XX_GPI_19		(64 + 11)
+#define IRQ_LPC32XX_U7_HCTS		(64 + 12)
+#define IRQ_LPC32XX_GPI_07		(64 + 15)
+#define IRQ_LPC32XX_SDIO		(64 + 18)
+#define IRQ_LPC32XX_U5_RX		(64 + 19)
+#define IRQ_LPC32XX_SPI1_DATAIN		(64 + 20)
+#define IRQ_LPC32XX_GPI_00		(64 + 22)
+#define IRQ_LPC32XX_GPI_01		(64 + 23)
+#define IRQ_LPC32XX_GPI_02		(64 + 24)
+#define IRQ_LPC32XX_GPI_03		(64 + 25)
+#define IRQ_LPC32XX_GPI_04		(64 + 26)
+#define IRQ_LPC32XX_GPI_05		(64 + 27)
+#define IRQ_LPC32XX_GPI_06		(64 + 28)
+#define IRQ_LPC32XX_SYSCLK		(64 + 31)
+
+#define NR_IRQS				96
+
+#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/memory.h b/arch/arm/mach-lpc32xx/include/mach/memory.h
new file mode 100644
index 0000000..b4d8156
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/memory.h
@@ -0,0 +1,28 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/memory.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset of bank 0
+ */
+#define PHYS_OFFSET	UL(0x80000000)
+
+#endif
+
diff --git a/arch/arm/mach-lpc32xx/include/mach/platform.h b/arch/arm/mach-lpc32xx/include/mach/platform.h
new file mode 100644
index 0000000..e01181f
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/platform.h
@@ -0,0 +1,697 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/platform.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_PLATFORM_H
+#define __ASM_ARCH_PLATFORM_H
+
+#define _REG(x)					(void __iomem *)(io_p2v(x))
+
+#define _SBF(f, v)				((v) << (f))
+#define _BIT(n)					_SBF(n, 1)
+
+/*
+ * AHB 0 physical base addresses
+ */
+#define LPC32XX_SLC_BASE			0x20020000
+#define LPC32XX_SSP0_BASE			0x20084000
+#define LPC32XX_SPI1_BASE			0x20088000
+#define LPC32XX_SSP1_BASE			0x2008C000
+#define LPC32XX_SPI2_BASE			0x20090000
+#define LPC32XX_I2S0_BASE			0x20094000
+#define LPC32XX_SD_BASE				0x20098000
+#define LPC32XX_I2S1_BASE			0x2009C000
+#define LPC32XX_MLC_BASE			0x200A8000
+#define LPC32XX_AHB0_START			LPC32XX_SLC_BASE
+#define LPC32XX_AHB0_SIZE			((LPC32XX_MLC_BASE -\
+						LPC32XX_SLC_BASE) + SZ_4K)
+/*
+ * AHB 1 physical base addresses
+ */
+#define LPC32XX_DMA_BASE			0x31000000
+#define LPC32XX_USB_BASE			0x31020000
+#define LPC32XX_USBH_BASE			0x31020000
+#define LPC32XX_USB_OTG_BASE			0x31020000
+#define LPC32XX_OTG_I2C_BASE			0x31020300
+#define LPC32XX_LCD_BASE			0x31040000
+#define LPC32XX_ETHERNET_BASE			0x31060000
+#define LPC32XX_EMC_BASE			0x31080000
+#define LPC32XX_ETB_CFG_BASE			0x310C0000
+#define LPC32XX_ETB_DATA_BASE			0x310E0000
+#define LPC32XX_AHB1_START			LPC32XX_DMA_BASE
+#define LPC32XX_AHB1_SIZE			((LPC32XX_EMC_BASE -\
+						LPC32XX_DMA_BASE) + SZ_4K)
+/*
+ * FAB physical base addresses
+ */
+#define LPC32XX_CLK_PM_BASE			0x40004000
+#define LPC32XX_MIC_BASE			0x40008000
+#define LPC32XX_SIC1_BASE			0x4000C000
+#define LPC32XX_SIC2_BASE			0x40010000
+#define LPC32XX_HS_UART1_BASE			0x40014000
+#define LPC32XX_HS_UART2_BASE			0x40018000
+#define LPC32XX_HS_UART7_BASE			0x4001C000
+#define LPC32XX_RTC_BASE			0x40024000
+#define LPC32XX_RTC_RAM_BASE			0x40024080
+#define LPC32XX_GPIO_BASE			0x40028000
+#define LPC32XX_PWM3_BASE			0x4002C000
+#define LPC32XX_PWM4_BASE			0x40030000
+#define LPC32XX_MSTIM_BASE			0x40034000
+#define LPC32XX_HSTIM_BASE			0x40038000
+#define LPC32XX_WDTIM_BASE			0x4003C000
+#define LPC32XX_DEBUG_CTRL_BASE			0x40040000
+#define LPC32XX_TIMER0_BASE			0x40044000
+#define LPC32XX_ADC_BASE			0x40048000
+#define LPC32XX_TIMER1_BASE			0x4004C000
+#define LPC32XX_KSCAN_BASE			0x40050000
+#define LPC32XX_UART_CTRL_BASE			0x40054000
+#define LPC32XX_TIMER2_BASE			0x40058000
+#define LPC32XX_PWM1_BASE			0x4005C000
+#define LPC32XX_PWM2_BASE			0x4005C004
+#define LPC32XX_TIMER3_BASE			0x40060000
+
+/*
+ * APB physical base addresses
+ */
+#define LPC32XX_UART3_BASE			0x40080000
+#define LPC32XX_UART4_BASE			0x40088000
+#define LPC32XX_UART5_BASE			0x40090000
+#define LPC32XX_UART6_BASE			0x40098000
+#define LPC32XX_I2C1_BASE			0x400A0000
+#define LPC32XX_I2C2_BASE			0x400A8000
+
+/*
+ * FAB and APB base and sizing
+ */
+#define LPC32XX_FABAPB_START			LPC32XX_CLK_PM_BASE
+#define LPC32XX_FABAPB_SIZE			((LPC32XX_I2C2_BASE -\
+						LPC32XX_CLK_PM_BASE) + SZ_4K)
+
+/*
+ * Internal memory Bases
+ */
+#define LPC32XX_IRAM_BASE			0x08000000
+#define LPC32XX_IROM_BASE			0x0C000000
+
+/*
+ * External Static Memory Bank Address Space Bases
+ */
+#define LPC32XX_EMC_CS0_BASE			0xE0000000
+#define LPC32XX_EMC_CS1_BASE			0xE1000000
+#define LPC32XX_EMC_CS2_BASE			0xE2000000
+#define LPC32XX_EMC_CS3_BASE			0xE3000000
+
+/*
+ * External SDRAM Memory Bank Address Space Bases
+ */
+#define LPC32XX_EMC_DYCS0_BASE			0x80000000
+#define LPC32XX_EMC_DYCS1_BASE			0xA0000000
+
+/*
+ * Clock and crystal information
+ */
+#define LPC32XX_MAIN_OSC_FREQ			13000000
+#define LPC32XX_CLOCK_OSC_FREQ			32768
+
+/*
+ * Clock and Power control register offsets
+ */
+#define _PMREG(x)				_REG(LPC32XX_CLK_PM_BASE + (x))
+#define LPC32XX_CLKPWR_DEBUG_CTRL		_PMREG(0x000)
+#define LPC32XX_CLKPWR_BOOTMAP			_PMREG(0x014)
+#define LPC32XX_CLKPWR_P01_ER			_PMREG(0x018)
+#define LPC32XX_CLKPWR_USBCLK_PDIV		_PMREG(0x01C)
+#define LPC32XX_CLKPWR_INT_ER			_PMREG(0x020)
+#define LPC32XX_CLKPWR_INT_RS			_PMREG(0x024)
+#define LPC32XX_CLKPWR_INT_SR			_PMREG(0x028)
+#define LPC32XX_CLKPWR_INT_AP			_PMREG(0x02C)
+#define LPC32XX_CLKPWR_PIN_ER			_PMREG(0x030)
+#define LPC32XX_CLKPWR_PIN_RS			_PMREG(0x034)
+#define LPC32XX_CLKPWR_PIN_SR			_PMREG(0x038)
+#define LPC32XX_CLKPWR_PIN_AP			_PMREG(0x03C)
+#define LPC32XX_CLKPWR_HCLK_DIV			_PMREG(0x040)
+#define LPC32XX_CLKPWR_PWR_CTRL			_PMREG(0x044)
+#define LPC32XX_CLKPWR_PLL397_CTRL		_PMREG(0x048)
+#define LPC32XX_CLKPWR_MAIN_OSC_CTRL		_PMREG(0x04C)
+#define LPC32XX_CLKPWR_SYSCLK_CTRL		_PMREG(0x050)
+#define LPC32XX_CLKPWR_LCDCLK_CTRL		_PMREG(0x054)
+#define LPC32XX_CLKPWR_HCLKPLL_CTRL		_PMREG(0x058)
+#define LPC32XX_CLKPWR_ADC_CLK_CTRL_1		_PMREG(0x060)
+#define LPC32XX_CLKPWR_USB_CTRL			_PMREG(0x064)
+#define LPC32XX_CLKPWR_SDRAMCLK_CTRL		_PMREG(0x068)
+#define LPC32XX_CLKPWR_DDR_LAP_NOM		_PMREG(0x06C)
+#define LPC32XX_CLKPWR_DDR_LAP_COUNT		_PMREG(0x070)
+#define LPC32XX_CLKPWR_DDR_LAP_DELAY		_PMREG(0x074)
+#define LPC32XX_CLKPWR_SSP_CLK_CTRL		_PMREG(0x078)
+#define LPC32XX_CLKPWR_I2S_CLK_CTRL		_PMREG(0x07C)
+#define LPC32XX_CLKPWR_MS_CTRL			_PMREG(0x080)
+#define LPC32XX_CLKPWR_MACCLK_CTRL		_PMREG(0x090)
+#define LPC32XX_CLKPWR_TEST_CLK_SEL		_PMREG(0x0A4)
+#define LPC32XX_CLKPWR_SFW_INT			_PMREG(0x0A8)
+#define LPC32XX_CLKPWR_I2C_CLK_CTRL		_PMREG(0x0AC)
+#define LPC32XX_CLKPWR_KEY_CLK_CTRL		_PMREG(0x0B0)
+#define LPC32XX_CLKPWR_ADC_CLK_CTRL		_PMREG(0x0B4)
+#define LPC32XX_CLKPWR_PWM_CLK_CTRL		_PMREG(0x0B8)
+#define LPC32XX_CLKPWR_TIMER_CLK_CTRL		_PMREG(0x0BC)
+#define LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1	_PMREG(0x0C0)
+#define LPC32XX_CLKPWR_SPI_CLK_CTRL		_PMREG(0x0C4)
+#define LPC32XX_CLKPWR_NAND_CLK_CTRL		_PMREG(0x0C8)
+#define LPC32XX_CLKPWR_UART3_CLK_CTRL		_PMREG(0x0D0)
+#define LPC32XX_CLKPWR_UART4_CLK_CTRL		_PMREG(0x0D4)
+#define LPC32XX_CLKPWR_UART5_CLK_CTRL		_PMREG(0x0D8)
+#define LPC32XX_CLKPWR_UART6_CLK_CTRL		_PMREG(0x0DC)
+#define LPC32XX_CLKPWR_IRDA_CLK_CTRL		_PMREG(0x0E0)
+#define LPC32XX_CLKPWR_UART_CLK_CTRL		_PMREG(0x0E4)
+#define LPC32XX_CLKPWR_DMA_CLK_CTRL		_PMREG(0x0E8)
+#define LPC32XX_CLKPWR_AUTOCLOCK		_PMREG(0x0EC)
+#define LPC32XX_CLKPWR_DEVID(x)			_PMREG(0x130 + (x))
+
+/*
+ * clkpwr_debug_ctrl register definitions
+*/
+#define LPC32XX_CLKPWR_VFP_CLOCK_ENABLE_BIT	_BIT(4)
+
+/*
+ * clkpwr_bootmap register definitions
+ */
+#define LPC32XX_CLKPWR_BOOTMAP_SEL_BIT		_BIT(1)
+
+/*
+ * clkpwr_start_gpio register bit definitions
+ */
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO23_BIT	_BIT(31)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO22_BIT	_BIT(30)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO21_BIT	_BIT(29)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO20_BIT	_BIT(28)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO19_BIT	_BIT(27)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO18_BIT	_BIT(26)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO17_BIT	_BIT(25)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO16_BIT	_BIT(24)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO15_BIT	_BIT(23)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO14_BIT	_BIT(22)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO13_BIT	_BIT(21)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO12_BIT	_BIT(20)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO11_BIT	_BIT(19)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO10_BIT	_BIT(18)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO9_BIT	_BIT(17)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO8_BIT	_BIT(16)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO7_BIT	_BIT(15)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO6_BIT	_BIT(14)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO5_BIT	_BIT(13)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO4_BIT	_BIT(12)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO3_BIT	_BIT(11)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO2_BIT	_BIT(10)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO1_BIT	_BIT(9)
+#define LPC32XX_CLKPWR_GPIOSRC_P1IO0_BIT	_BIT(8)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO7_BIT	_BIT(7)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO6_BIT	_BIT(6)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO5_BIT	_BIT(5)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO4_BIT	_BIT(4)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO3_BIT	_BIT(3)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO2_BIT	_BIT(2)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO1_BIT	_BIT(1)
+#define LPC32XX_CLKPWR_GPIOSRC_P0IO0_BIT	_BIT(0)
+
+/*
+ * clkpwr_usbclk_pdiv register definitions
+ */
+#define LPC32XX_CLKPWR_SET_PLL_USBPDIV(n)	((n) & 0xF)
+#define LPC32XX_CLKPWR_USBPDIV_PLL_MASK		0xF
+
+/*
+ * clkpwr_start_int, clkpwr_start_raw_sts_int, clkpwr_start_sts_int,
+ * clkpwr_start_pol_int, register bit definitions
+ */
+#define LPC32XX_CLKPWR_INTSRC_ADC_BIT		_BIT(31)
+#define LPC32XX_CLKPWR_INTSRC_TS_P_BIT		_BIT(30)
+#define LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT	_BIT(29)
+#define LPC32XX_CLKPWR_INTSRC_USBAHNEEDCLK_BIT	_BIT(26)
+#define LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT	_BIT(25)
+#define LPC32XX_CLKPWR_INTSRC_RTC_BIT		_BIT(24)
+#define LPC32XX_CLKPWR_INTSRC_USBNEEDCLK_BIT	_BIT(23)
+#define LPC32XX_CLKPWR_INTSRC_USB_BIT		_BIT(22)
+#define LPC32XX_CLKPWR_INTSRC_I2C_BIT		_BIT(21)
+#define LPC32XX_CLKPWR_INTSRC_USBOTGTIMER_BIT	_BIT(20)
+#define LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT	_BIT(19)
+#define LPC32XX_CLKPWR_INTSRC_KEY_BIT		_BIT(16)
+#define LPC32XX_CLKPWR_INTSRC_MAC_BIT		_BIT(7)
+#define LPC32XX_CLKPWR_INTSRC_P0P1_BIT		_BIT(6)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT	_BIT(5)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT	_BIT(4)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT	_BIT(3)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT	_BIT(2)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT	_BIT(1)
+#define LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT	_BIT(0)
+
+/*
+ * clkpwr_start_pin, clkpwr_start_raw_sts_pin, clkpwr_start_sts_pin,
+ * clkpwr_start_pol_pin register bit definitions
+ */
+#define LPC32XX_CLKPWR_EXTSRC_U7_RX_BIT		_BIT(31)
+#define LPC32XX_CLKPWR_EXTSRC_U7_HCTS_BIT	_BIT(30)
+#define LPC32XX_CLKPWR_EXTSRC_U6_IRRX_BIT	_BIT(28)
+#define LPC32XX_CLKPWR_EXTSRC_U5_RX_BIT		_BIT(26)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_28_BIT	_BIT(25)
+#define LPC32XX_CLKPWR_EXTSRC_U3_RX_BIT		_BIT(24)
+#define LPC32XX_CLKPWR_EXTSRC_U2_HCTS_BIT	_BIT(23)
+#define LPC32XX_CLKPWR_EXTSRC_U2_RX_BIT		_BIT(22)
+#define LPC32XX_CLKPWR_EXTSRC_U1_RX_BIT		_BIT(21)
+#define LPC32XX_CLKPWR_EXTSRC_MSDIO_INT_BIT	_BIT(18)
+#define LPC32XX_CLKPWR_EXTSRC_MSDIO_SRT_BIT	_BIT(17)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT	_BIT(16)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_05_BIT	_BIT(15)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_04_BIT	_BIT(14)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_03_BIT	_BIT(13)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_02_BIT	_BIT(12)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_01_BIT	_BIT(11)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_00_BIT	_BIT(10)
+#define LPC32XX_CLKPWR_EXTSRC_SYSCLKEN_BIT	_BIT(9)
+#define LPC32XX_CLKPWR_EXTSRC_SPI1_DATIN_BIT	_BIT(8)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT	_BIT(7)
+#define LPC32XX_CLKPWR_EXTSRC_SPI2_DATIN_BIT	_BIT(6)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_19_BIT	_BIT(5)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_09_BIT	_BIT(4)
+#define LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT	_BIT(3)
+
+/*
+ * clkpwr_hclk_div register definitions
+ */
+#define LPC32XX_CLKPWR_HCLKDIV_DDRCLK_STOP	(0x0 << 7)
+#define LPC32XX_CLKPWR_HCLKDIV_DDRCLK_NORM	(0x1 << 7)
+#define LPC32XX_CLKPWR_HCLKDIV_DDRCLK_HALF	(0x2 << 7)
+#define LPC32XX_CLKPWR_HCLKDIV_PCLK_DIV(n)	(((n) & 0x1F) << 2)
+#define LPC32XX_CLKPWR_HCLKDIV_DIV_2POW(n)	((n) & 0x3)
+
+/*
+ * clkpwr_pwr_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_CTRL_FORCE_PCLK		_BIT(10)
+#define LPC32XX_CLKPWR_SDRAM_SELF_RFSH		_BIT(9)
+#define LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH	_BIT(8)
+#define LPC32XX_CLKPWR_AUTO_SDRAM_SELF_RFSH	_BIT(7)
+#define LPC32XX_CLKPWR_HIGHCORE_STATE_BIT	_BIT(5)
+#define LPC32XX_CLKPWR_SYSCLKEN_STATE_BIT	_BIT(4)
+#define LPC32XX_CLKPWR_SYSCLKEN_GPIO_EN		_BIT(3)
+#define LPC32XX_CLKPWR_SELECT_RUN_MODE		_BIT(2)
+#define LPC32XX_CLKPWR_HIGHCORE_GPIO_EN		_BIT(1)
+#define LPC32XX_CLKPWR_STOP_MODE_CTRL		_BIT(0)
+
+/*
+ * clkpwr_pll397_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_PLL397_MSLOCK_STS	_BIT(10)
+#define LPC32XX_CLKPWR_PLL397_BYPASS		_BIT(9)
+#define LPC32XX_CLKPWR_PLL397_BIAS_NORM		0x000
+#define LPC32XX_CLKPWR_PLL397_BIAS_N12_5	0x040
+#define LPC32XX_CLKPWR_PLL397_BIAS_N25		0x080
+#define LPC32XX_CLKPWR_PLL397_BIAS_N37_5	0x0C0
+#define LPC32XX_CLKPWR_PLL397_BIAS_P12_5	0x100
+#define LPC32XX_CLKPWR_PLL397_BIAS_P25		0x140
+#define LPC32XX_CLKPWR_PLL397_BIAS_P37_5	0x180
+#define LPC32XX_CLKPWR_PLL397_BIAS_P50		0x1C0
+#define LPC32XX_CLKPWR_PLL397_BIAS_MASK		0x1C0
+#define LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS	_BIT(1)
+#define LPC32XX_CLKPWR_SYSCTRL_PLL397_STS	_BIT(0)
+
+/*
+ * clkpwr_main_osc_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_MOSC_ADD_CAP(n)		(((n) & 0x7F) << 2)
+#define LPC32XX_CLKPWR_MOSC_CAP_MASK		(0x7F << 2)
+#define LPC32XX_CLKPWR_TEST_MODE		_BIT(1)
+#define LPC32XX_CLKPWR_MOSC_DISABLE		_BIT(0)
+
+/*
+ * clkpwr_sysclk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_SYSCTRL_BP_TRIG(n)	(((n) & 0x3FF) << 2)
+#define LPC32XX_CLKPWR_SYSCTRL_BP_MASK		(0x3FF << 2)
+#define LPC32XX_CLKPWR_SYSCTRL_USEPLL397	_BIT(1)
+#define LPC32XX_CLKPWR_SYSCTRL_SYSCLKMUX	_BIT(0)
+
+/*
+ * clkpwr_lcdclk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT12	0x000
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16	0x040
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT15	0x080
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT24	0x0C0
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_STN4M	0x100
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_STN8C	0x140
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_DSTN4M	0x180
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_DSTN8C	0x1C0
+#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK	0x01C0
+#define LPC32XX_CLKPWR_LCDCTRL_CLK_EN		0x020
+#define LPC32XX_CLKPWR_LCDCTRL_SET_PSCALE(n)	((n - 1) & 0x1F)
+#define LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK	0x001F
+
+/*
+ * clkpwr_hclkpll_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_HCLKPLL_POWER_UP		_BIT(16)
+#define LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS	_BIT(15)
+#define LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS	_BIT(14)
+#define LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK	_BIT(13)
+#define LPC32XX_CLKPWR_HCLKPLL_POSTDIV_2POW(n)	(((n) & 0x3) << 11)
+#define LPC32XX_CLKPWR_HCLKPLL_PREDIV_PLUS1(n)	(((n) & 0x3) << 9)
+#define LPC32XX_CLKPWR_HCLKPLL_PLLM(n)		(((n) & 0xFF) << 1)
+#define LPC32XX_CLKPWR_HCLKPLL_PLL_STS		_BIT(0)
+
+/*
+ * clkpwr_adc_clk_ctrl_1 register definitions
+ */
+#define LPC32XX_CLKPWR_ADCCTRL1_RTDIV(n)	(((n) & 0xFF) << 0)
+#define LPC32XX_CLKPWR_ADCCTRL1_PCLK_SEL	_BIT(8)
+
+/*
+ * clkpwr_usb_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_USBCTRL_HCLK_EN		_BIT(24)
+#define LPC32XX_CLKPWR_USBCTRL_USBI2C_EN	_BIT(23)
+#define LPC32XX_CLKPWR_USBCTRL_USBDVND_EN	_BIT(22)
+#define LPC32XX_CLKPWR_USBCTRL_USBHSTND_EN	_BIT(21)
+#define LPC32XX_CLKPWR_USBCTRL_PU_ADD		(0x0 << 19)
+#define LPC32XX_CLKPWR_USBCTRL_BUS_KEEPER	(0x1 << 19)
+#define LPC32XX_CLKPWR_USBCTRL_PD_ADD		(0x3 << 19)
+#define LPC32XX_CLKPWR_USBCTRL_CLK_EN2		_BIT(18)
+#define LPC32XX_CLKPWR_USBCTRL_CLK_EN1		_BIT(17)
+#define LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP	_BIT(16)
+#define LPC32XX_CLKPWR_USBCTRL_CCO_BYPASS	_BIT(15)
+#define LPC32XX_CLKPWR_USBCTRL_POSTDIV_BYPASS	_BIT(14)
+#define LPC32XX_CLKPWR_USBCTRL_FDBK_SEL_FCLK	_BIT(13)
+#define LPC32XX_CLKPWR_USBCTRL_POSTDIV_2POW(n)	(((n) & 0x3) << 11)
+#define LPC32XX_CLKPWR_USBCTRL_PREDIV_PLUS1(n)	(((n) & 0x3) << 9)
+#define LPC32XX_CLKPWR_USBCTRL_FDBK_PLUS1(n)	(((n) & 0xFF) << 1)
+#define LPC32XX_CLKPWR_USBCTRL_PLL_STS		_BIT(0)
+
+/*
+ * clkpwr_sdramclk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_SDRCLK_FASTSLEW_CLK	_BIT(22)
+#define LPC32XX_CLKPWR_SDRCLK_FASTSLEW		_BIT(21)
+#define LPC32XX_CLKPWR_SDRCLK_FASTSLEW_DAT	_BIT(20)
+#define LPC32XX_CLKPWR_SDRCLK_SW_DDR_RESET	_BIT(19)
+#define LPC32XX_CLKPWR_SDRCLK_HCLK_DLY(n)	(((n) & 0x1F) << 14)
+#define LPC32XX_CLKPWR_SDRCLK_DLY_ADDR_STS	_BIT(13)
+#define LPC32XX_CLKPWR_SDRCLK_SENS_FACT(n)	(((n) & 0x7) << 10)
+#define LPC32XX_CLKPWR_SDRCLK_USE_CAL		_BIT(9)
+#define LPC32XX_CLKPWR_SDRCLK_DO_CAL		_BIT(8)
+#define LPC32XX_CLKPWR_SDRCLK_CAL_ON_RTC	_BIT(7)
+#define LPC32XX_CLKPWR_SDRCLK_DQS_DLY(n)	(((n) & 0x1F) << 2)
+#define LPC32XX_CLKPWR_SDRCLK_USE_DDR		_BIT(1)
+#define LPC32XX_CLKPWR_SDRCLK_CLK_DIS		_BIT(0)
+
+/*
+ * clkpwr_ssp_blk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP1RX	_BIT(5)
+#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP1TX	_BIT(4)
+#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP0RX	_BIT(3)
+#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP0TX	_BIT(2)
+#define LPC32XX_CLKPWR_SSPCTRL_SSPCLK1_EN	_BIT(1)
+#define LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN	_BIT(0)
+
+/*
+ * clkpwr_i2s_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_I2SCTRL_I2S1_RX_FOR_TX	_BIT(6)
+#define LPC32XX_CLKPWR_I2SCTRL_I2S1_TX_FOR_RX	_BIT(5)
+#define LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA	_BIT(4)
+#define LPC32XX_CLKPWR_I2SCTRL_I2S0_RX_FOR_TX	_BIT(3)
+#define LPC32XX_CLKPWR_I2SCTRL_I2S0_TX_FOR_RX	_BIT(2)
+#define LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN	_BIT(1)
+#define LPC32XX_CLKPWR_I2SCTRL_I2SCLK0_EN	_BIT(0)
+
+/*
+ * clkpwr_ms_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_MSCARD_MSDIO_PIN_DIS	_BIT(10)
+#define LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN	_BIT(9)
+#define LPC32XX_CLKPWR_MSCARD_MSDIO23_DIS	_BIT(8)
+#define LPC32XX_CLKPWR_MSCARD_MSDIO1_DIS	_BIT(7)
+#define LPC32XX_CLKPWR_MSCARD_MSDIO0_DIS	_BIT(6)
+#define LPC32XX_CLKPWR_MSCARD_SDCARD_EN		_BIT(5)
+#define LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(n)	((n) & 0xF)
+
+/*
+ * clkpwr_macclk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_MACCTRL_NO_ENET_PIS	0x00
+#define LPC32XX_CLKPWR_MACCTRL_USE_MII_PINS	0x08
+#define LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS	0x18
+#define LPC32XX_CLKPWR_MACCTRL_PINS_MSK		0x18
+#define LPC32XX_CLKPWR_MACCTRL_DMACLK_EN	_BIT(2)
+#define LPC32XX_CLKPWR_MACCTRL_MMIOCLK_EN	_BIT(1)
+#define LPC32XX_CLKPWR_MACCTRL_HRCCLK_EN	_BIT(0)
+
+/*
+ * clkpwr_test_clk_sel register definitions
+ */
+#define LPC32XX_CLKPWR_TESTCLK1_SEL_PERCLK	(0x0 << 5)
+#define LPC32XX_CLKPWR_TESTCLK1_SEL_RTC		(0x1 << 5)
+#define LPC32XX_CLKPWR_TESTCLK1_SEL_MOSC	(0x2 << 5)
+#define LPC32XX_CLKPWR_TESTCLK1_SEL_MASK	(0x3 << 5)
+#define LPC32XX_CLKPWR_TESTCLK_TESTCLK1_EN	_BIT(4)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_HCLK	(0x0 << 1)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_PERCLK	(0x1 << 1)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_USBCLK	(0x2 << 1)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC	(0x5 << 1)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_PLL397	(0x7 << 1)
+#define LPC32XX_CLKPWR_TESTCLK2_SEL_MASK	(0x7 << 1)
+#define LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN	_BIT(0)
+
+/*
+ * clkpwr_sw_int register definitions
+ */
+#define LPC32XX_CLKPWR_SW_INT(n)		(_BIT(0) | (((n) & 0x7F) << 1))
+#define LPC32XX_CLKPWR_SW_GET_ARG(n)		(((n) & 0xFE) >> 1)
+
+/*
+ * clkpwr_i2c_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE	_BIT(4)
+#define LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE	_BIT(3)
+#define LPC32XX_CLKPWR_I2CCLK_I2C1HI_DRIVE	_BIT(2)
+#define LPC32XX_CLKPWR_I2CCLK_I2C2CLK_EN	_BIT(1)
+#define LPC32XX_CLKPWR_I2CCLK_I2C1CLK_EN	_BIT(0)
+
+/*
+ * clkpwr_key_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_KEYCLKCTRL_CLK_EN	0x1
+
+/*
+ * clkpwr_adc_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_ADC32CLKCTRL_CLK_EN	0x1
+
+/*
+ * clkpwr_pwm_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_PWMCLK_PWM2_DIV(n)	(((n) & 0xF) << 8)
+#define LPC32XX_CLKPWR_PWMCLK_PWM1_DIV(n)	(((n) & 0xF) << 4)
+#define LPC32XX_CLKPWR_PWMCLK_PWM2SEL_PCLK	0x8
+#define LPC32XX_CLKPWR_PWMCLK_PWM2CLK_EN	0x4
+#define LPC32XX_CLKPWR_PWMCLK_PWM1SEL_PCLK	0x2
+#define LPC32XX_CLKPWR_PWMCLK_PWM1CLK_EN	0x1
+
+/*
+ * clkpwr_timer_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_PWMCLK_HSTIMER_EN	0x2
+#define LPC32XX_CLKPWR_PWMCLK_WDOG_EN		0x1
+
+/*
+ * clkpwr_timers_pwms_clk_ctrl_1 register definitions
+ */
+#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER3_EN	0x20
+#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER2_EN	0x10
+#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN	0x08
+#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN	0x04
+#define LPC32XX_CLKPWR_TMRPWMCLK_PWM4_EN	0x02
+#define LPC32XX_CLKPWR_TMRPWMCLK_PWM3_EN	0x01
+
+/*
+ * clkpwr_spi_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_SPICLK_SET_SPI2DATIO	0x80
+#define LPC32XX_CLKPWR_SPICLK_SET_SPI2CLK	0x40
+#define LPC32XX_CLKPWR_SPICLK_USE_SPI2		0x20
+#define LPC32XX_CLKPWR_SPICLK_SPI2CLK_EN	0x10
+#define LPC32XX_CLKPWR_SPICLK_SET_SPI1DATIO	0x08
+#define LPC32XX_CLKPWR_SPICLK_SET_SPI1CLK	0x04
+#define LPC32XX_CLKPWR_SPICLK_USE_SPI1		0x02
+#define LPC32XX_CLKPWR_SPICLK_SPI1CLK_EN	0x01
+
+/*
+ * clkpwr_nand_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_NANDCLK_INTSEL_MLC	0x20
+#define LPC32XX_CLKPWR_NANDCLK_DMA_RNB		0x10
+#define LPC32XX_CLKPWR_NANDCLK_DMA_INT		0x08
+#define LPC32XX_CLKPWR_NANDCLK_SEL_SLC		0x04
+#define LPC32XX_CLKPWR_NANDCLK_MLCCLK_EN	0x02
+#define LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN	0x01
+
+/*
+ * clkpwr_uart3_clk_ctrl, clkpwr_uart4_clk_ctrl, clkpwr_uart5_clk_ctrl
+ * and clkpwr_uart6_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_UART_Y_DIV(y)		((y) & 0xFF)
+#define LPC32XX_CLKPWR_UART_X_DIV(x)		(((x) & 0xFF) << 8)
+#define LPC32XX_CLKPWR_UART_USE_HCLK		_BIT(16)
+
+/*
+ * clkpwr_irda_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_IRDA_Y_DIV(y)		((y) & 0xFF)
+#define LPC32XX_CLKPWR_IRDA_X_DIV(x)		(((x) & 0xFF) << 8)
+
+/*
+ * clkpwr_uart_clk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_UARTCLKCTRL_UART6_EN	_BIT(3)
+#define LPC32XX_CLKPWR_UARTCLKCTRL_UART5_EN	_BIT(2)
+#define LPC32XX_CLKPWR_UARTCLKCTRL_UART4_EN	_BIT(1)
+#define LPC32XX_CLKPWR_UARTCLKCTRL_UART3_EN	_BIT(0)
+
+/*
+ * clkpwr_dmaclk_ctrl register definitions
+ */
+#define LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN	0x1
+
+/*
+ * clkpwr_autoclock register definitions
+ */
+#define LPC32XX_CLKPWR_AUTOCLK_USB_EN		0x40
+#define LPC32XX_CLKPWR_AUTOCLK_IRAM_EN		0x02
+#define LPC32XX_CLKPWR_AUTOCLK_IROM_EN		0x01
+
+/*
+ * Interrupt controller register offsets
+ */
+#define LPC32XX_INTC_MASK(x)			_REG((x) + 0x00)
+#define LPC32XX_INTC_RAW_STAT(x)		_REG((x) + 0x04)
+#define LPC32XX_INTC_STAT(x)			_REG((x) + 0x08)
+#define LPC32XX_INTC_POLAR(x)			_REG((x) + 0x0C)
+#define LPC32XX_INTC_ACT_TYPE(x)		_REG((x) + 0x10)
+#define LPC32XX_INTC_TYPE(x)			_REG((x) + 0x14)
+
+/*
+ * Timer/counter register offsets
+ */
+#define LCP32XX_TIMER_IR(x)			_REG((x) + 0x00)
+#define LCP32XX_TIMER_TCR(x)			_REG((x) + 0x04)
+#define LCP32XX_TIMER_TC(x)			_REG((x) + 0x08)
+#define LCP32XX_TIMER_PR(x)			_REG((x) + 0x0C)
+#define LCP32XX_TIMER_PC(x)			_REG((x) + 0x10)
+#define LCP32XX_TIMER_MCR(x)			_REG((x) + 0x14)
+#define LCP32XX_TIMER_MR0(x)			_REG((x) + 0x18)
+#define LCP32XX_TIMER_MR1(x)			_REG((x) + 0x1C)
+#define LCP32XX_TIMER_MR2(x)			_REG((x) + 0x20)
+#define LCP32XX_TIMER_MR3(x)			_REG((x) + 0x24)
+#define LCP32XX_TIMER_CCR(x)			_REG((x) + 0x28)
+#define LCP32XX_TIMER_CR0(x)			_REG((x) + 0x2C)
+#define LCP32XX_TIMER_CR1(x)			_REG((x) + 0x30)
+#define LCP32XX_TIMER_CR2(x)			_REG((x) + 0x34)
+#define LCP32XX_TIMER_CR3(x)			_REG((x) + 0x38)
+#define LCP32XX_TIMER_EMR(x)			_REG((x) + 0x3C)
+#define LCP32XX_TIMER_CTCR(x)			_REG((x) + 0x70)
+
+/*
+ * ir register definitions
+ */
+#define LCP32XX_TIMER_CNTR_MTCH_BIT(n)		(1 << ((n) & 0x3))
+#define LCP32XX_TIMER_CNTR_CAPT_BIT(n)		(1 << (4 + ((n) & 0x3)))
+
+/*
+ * tcr register definitions
+ */
+#define LCP32XX_TIMER_CNTR_TCR_EN		0x1
+#define LCP32XX_TIMER_CNTR_TCR_RESET		0x2
+
+/*
+ * mcr register definitions
+ */
+#define LCP32XX_TIMER_CNTR_MCR_MTCH(n)		(0x1 << ((n) * 3))
+#define LCP32XX_TIMER_CNTR_MCR_RESET(n)		(0x1 << (((n) * 3) + 1))
+#define LCP32XX_TIMER_CNTR_MCR_STOP(n)		(0x1 << (((n) * 3) + 2))
+
+/*
+ * Standard UART register offsets
+ */
+#define LPC32XX_UART_DLL_FIFO(x)		_REG((x) + 0x00)
+#define LPC32XX_UART_DLM_IER(x)			_REG((x) + 0x04)
+#define LPC32XX_UART_IIR_FCR(x)			_REG((x) + 0x08)
+#define LPC32XX_UART_LCR(x)			_REG((x) + 0x0C)
+#define LPC32XX_UART_MODEM_CTRL(x)		_REG((x) + 0x10)
+#define LPC32XX_UART_LSR(x)			_REG((x) + 0x14)
+#define LPC32XX_UART_MODEM_STATUS(x)		_REG((x) + 0x18)
+#define LPC32XX_UART_RXLEV(x)			_REG((x) + 0x1C)
+
+/*
+ * UART control structure offsets
+ */
+#define _UCREG(x)				_REG(LPC32XX_UART_CTRL_BASE +\
+						(x))
+#define LPC32XX_UARTCTL_CTRL			_UCREG(0x00)
+#define LPC32XX_UARTCTL_CLKMODE			_UCREG(0x04)
+#define LPC32XX_UARTCTL_CLOOP			_UCREG(0x08)
+
+/*
+ * ctrl register definitions
+ */
+#define LPC32XX_UART_U3_MD_CTRL_EN		_BIT(11)
+#define LPC32XX_UART_IRRX6_INV_EN		_BIT(10)
+#define LPC32XX_UART_HDPX_EN			_BIT(9)
+#define LPC32XX_UART_UART6_IRDAMOD_BYPASS	_BIT(5)
+#define LPC32XX_RT_IRTX6_INV_EN			_BIT(4)
+#define LPC32XX_RT_IRTX6_INV_MIR_EN		_BIT(3)
+#define LPC32XX_RT_RX_IRPULSE_3_16_115K		_BIT(2)
+#define LPC32XX_RT_TX_IRPULSE_3_16_115K		_BIT(1)
+#define LPC32XX_UART_U5_ROUTE_TO_USB		_BIT(0)
+
+/*
+ * clkmode register definitions
+ */
+#define LPC32XX_UART_ENABLED_CLOCKS(n)		(((n) >> 16) & 0x7F)
+#define LPC32XX_UART_ENABLED_CLOCK(n, u)	(((n) >> (16 + (u))) & 0x1)
+#define LPC32XX_UART_ENABLED_CLKS_ANY		_BIT(14)
+#define LPC32XX_UART_CLKMODE_OFF		0x0
+#define LPC32XX_UART_CLKMODE_ON			0x1
+#define LPC32XX_UART_CLKMODE_AUTO		0x2
+#define LPC32XX_UART_CLKMODE_MASK(u)		(0x3 << ((((u) - 3) * 2) + 4))
+#define LPC32XX_UART_CLKMODE_LOAD(m, u)		((m) << ((((u) - 3) * 2) + 4))
+
+/*
+ * GPIO Module Register offsets
+ */
+#define _GPREG(x)				_REG(LPC32XX_GPIO_BASE + (x))
+#define LPC32XX_GPIO_P_MUX_SET			_GPREG(0x100)
+#define LPC32XX_GPIO_P_MUX_CLR			_GPREG(0x104)
+#define LPC32XX_GPIO_P_MUX_STATE		_GPREG(0x108)
+#define LPC32XX_GPIO_P3_MUX_SET			_GPREG(0x110)
+#define LPC32XX_GPIO_P3_MUX_CLR			_GPREG(0x114)
+#define LPC32XX_GPIO_P3_MUX_STATE		_GPREG(0x118)
+#define LPC32XX_GPIO_P0_MUX_SET			_GPREG(0x120)
+#define LPC32XX_GPIO_P0_MUX_CLR			_GPREG(0x124)
+#define LPC32XX_GPIO_P0_MUX_STATE		_GPREG(0x128)
+#define LPC32XX_GPIO_P1_MUX_SET			_GPREG(0x130)
+#define LPC32XX_GPIO_P1_MUX_CLR			_GPREG(0x134)
+#define LPC32XX_GPIO_P1_MUX_STATE		_GPREG(0x138)
+
+#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/system.h b/arch/arm/mach-lpc32xx/include/mach/system.h
new file mode 100644
index 0000000..df3b0de
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/system.h
@@ -0,0 +1,52 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/system.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	extern void lpc32xx_watchdog_reset(void);
+
+	switch (mode) {
+	case 's':
+	case 'h':
+		printk(KERN_CRIT "RESET: Rebooting system\n");
+
+		/* Disable interrupts */
+		local_irq_disable();
+
+		lpc32xx_watchdog_reset();
+		break;
+
+	default:
+		/* Do nothing */
+		break;
+	}
+
+	/* Wait for watchdog to reset system */
+	while (1)
+		;
+}
+
+#endif
diff --git a/arch/arm/mach-lpc32xx/include/mach/timex.h b/arch/arm/mach-lpc32xx/include/mach/timex.h
new file mode 100644
index 0000000..1b2a20f
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/timex.h
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/timex.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+/*
+ * Rate in Hz of the main system oscillator. This value should match
+ * the value 'MAIN_OSC_FREQ' in platform.h
+ */
+#define CLOCK_TICK_RATE	13000000
+
+#endif
+
diff --git a/arch/arm/mach-lpc32xx/include/mach/uncompress.h b/arch/arm/mach-lpc32xx/include/mach/uncompress.h
new file mode 100644
index 0000000..7effa54
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/uncompress.h
@@ -0,0 +1,63 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/uncompress.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARM_ARCH_UNCOMPRESS_H
+#define __ASM_ARM_ARCH_UNCOMPRESS_H
+
+#include <linux/io.h>
+
+#include <mach/platform.h>
+
+/*
+ * Uncompress output is hardcoded to standard UART 5
+ */
+
+#define UART_FIFO_CTL_TX_RESET	(1 << 2)
+#define UART_STATUS_TX_MT	(1 << 6)
+
+#define LPC32XX_UART_DLLFIFO_O	0x00
+#define LPC32XX_UART_IIRFCR_O	0x08
+#define LPC32XX_UART_LSR_O	0x14
+
+#define LPC32XX_SUART_DATA	(*(volatile unsigned long *)\
+				(LPC32XX_UART5_BASE + LPC32XX_UART_DLLFIFO_O))
+#define LPC32XX_SUART_STATUS	(*(volatile unsigned long *)\
+				(LPC32XX_UART5_BASE + LPC32XX_UART_LSR_O))
+#define LPC32XX_SUART_FIFOCTRL	(*(volatile unsigned long *)\
+				(LPC32XX_UART5_BASE + LPC32XX_UART_IIRFCR_O))
+
+static inline void putc(int ch)
+{
+	/* Wait for transmit FIFO to empty */
+	while ((LPC32XX_SUART_STATUS & UART_STATUS_TX_MT) == 0)
+		;
+
+	LPC32XX_SUART_DATA = (u32) ch;
+}
+
+static inline void flush(void)
+{
+	LPC32XX_SUART_FIFOCTRL |= UART_FIFO_CTL_TX_RESET;
+}
+
+/* NULL functions; we don't presently need them */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif
+
diff --git a/arch/arm/mach-lpc32xx/include/mach/vmalloc.h b/arch/arm/mach-lpc32xx/include/mach/vmalloc.h
new file mode 100644
index 0000000..d1d936c
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/vmalloc.h
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/vmalloc.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END	0xF0000000
+
+#endif
-- 
1.6.6

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

* [PATCH 02/14] ARM: LPC32XX: Debug and IRQ macros
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
  2010-02-09  0:11 ` [PATCH 01/14] ARM: LPC32XX: Initial architecture header files wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-09  9:45   ` Uwe Kleine-König
  2010-02-09  0:11 ` [PATCH 03/14] ARM: LPC32XX: Clock driver wellsk40 at gmail.com
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

Debug (printascii) and IRQ handler macros for the LPC32XX
architecture

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 arch/arm/mach-lpc32xx/include/mach/debug-macro.S |   54 ++++++++++++++++++++++
 arch/arm/mach-lpc32xx/include/mach/entry-macro.S |   47 +++++++++++++++++++
 2 files changed, 101 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-lpc32xx/include/mach/debug-macro.S b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
new file mode 100644
index 0000000..cd62e2f
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
@@ -0,0 +1,54 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/debug-macro.S
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+
+#define LPC32XX_UART_DLL_FIFO_OFS	0x00
+#define LPC32XX_UART_LSR_OFS		0x14
+
+/*
+ * Debug output is hardcoded to standard UART 5
+*/
+
+	.macro	addruart,rx
+	mrc	p15, 0, \rx, c1, c0
+	tst	\rx, #1				@ MMU enabled?
+	ldr	\rx, =LPC32XX_UART5_BASE	@ physical
+	beq	1003f
+	ldr	\rx, =IO_ADDRESS(LPC32XX_UART5_BASE) @ virtual
+1003:
+	.endm
+
+	.macro	senduart,rd,rx
+	str	\rd, [\rx, #LPC32XX_UART_DLL_FIFO_OFS]
+	.endm
+
+	.macro	busyuart,rd,rx
+1002:
+	ldr	\rd, [\rx, #LPC32XX_UART_LSR_OFS]
+	tst	\rd, #(1 << 6)
+	beq	1002b
+	.endm
+
+	.macro	waituart,rd,rx
+1001:
+	ldr	\rd, [\rx, #LPC32XX_UART_LSR_OFS]
+	tst	\rd, #(1 << 5)
+	beq	1001b
+	.endm
diff --git a/arch/arm/mach-lpc32xx/include/mach/entry-macro.S b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
new file mode 100644
index 0000000..870227c
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
@@ -0,0 +1,47 @@
+/*
+ * arch/arm/mach-lpc32xx/include/mach/entry-macro.S
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+
+#define LPC32XX_INTC_MASKED_STATUS_OFS	0x8
+
+	.macro	disable_fiq
+	.endm
+
+	.macro  get_irqnr_preamble, base, tmp
+	ldr	\base, =IO_ADDRESS(LPC32XX_MIC_BASE)
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
+/*
+ * Return IRQ number in irqnr. Also return processor Z flag status in CPSR
+ * as set if an interrupt is pending.
+ */
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr	\irqstat, [\base, #LPC32XX_INTC_MASKED_STATUS_OFS]
+	clz	\irqnr, \irqstat
+	rsb	\irqnr, \irqnr, #31
+	teq	\irqstat, #0
+	.endm
+
+	.macro	irq_prio_table
+	.endm
+
-- 
1.6.6

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

* [PATCH 03/14] ARM: LPC32XX: Clock driver
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
  2010-02-09  0:11 ` [PATCH 01/14] ARM: LPC32XX: Initial architecture header files wellsk40 at gmail.com
  2010-02-09  0:11 ` [PATCH 02/14] ARM: LPC32XX: Debug and IRQ macros wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-09 10:39   ` Uwe Kleine-König
  2010-02-09  0:11 ` [PATCH 04/14] ARM: LPC32XX: GPIO, timer, and IRQ drivers wellsk40 at gmail.com
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

Clock driver for the LPC32XX architecture

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 arch/arm/mach-lpc32xx/clock.c | 1078 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-lpc32xx/clock.h |   37 ++
 2 files changed, 1115 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c
new file mode 100644
index 0000000..4f0b882
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/clock.c
@@ -0,0 +1,1078 @@
+/*
+ * arch/arm/mach-lpc32xx/clock.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * LPC32xx clock mamagement driver overview
+ *
+ * The LPC32XX contains a number of high level system clocks that can be
+ * generated from different sources. These system clocks are used to
+ * generate the CPU and bus rates and the individual peripheral clocks in
+ * the system. When Linux is started by the boot loader, the system
+ * clocks are already running. Stopping a system clock during normal
+ * Linux operation should never be attempted, as peripherals that require
+ * those clocks will quit working (ie, DRAM).
+ *
+ * The LPC32xx high level clock tree looks as follows. Clocks marked with
+ * an asterisk are always on and cannot be disabled. Clocks marked with
+ * an ampersand can only be disabled in CPU suspend mode. Clocks marked
+ * with a carot are always on if it is the selected clock for the SYSCLK
+ * source. The clock that isn't used for SYSCLK can be enabled and
+ * disabled normally.
+ *                               32KHz oscillator*
+ *                               /      |      \
+ *                             RTC*   PLL397^ TOUCH
+ *                                     /
+ *               Main oscillator^     /
+ *                   |        \      /
+ *                   |         SYSCLK&
+ *                   |            \
+ *                   |             \
+ *                USB_PLL       HCLK_PLL&
+ *                   |           |    |
+ *            USB host/device  PCLK&  |
+ *                               |    |
+ *                             Peripherals
+ *
+ * The CPU and chip bus rates are derived from the HCLK PLL, which can
+ * generate various clock rates up to 266MHz and beyond. The internal bus
+ * rates (PCLK and HCLK) are generated from dividers based on the HCLK
+ * PLL rate. HCLK can be a ratio of 1:1, 1:2, or 1:4 or HCLK PLL rate,
+ * while PCLK can be 1:1 to 1:32 of HCLK PLL rate. Most peripherals high
+ * level clocks are based on either HCLK or PCLK, but have their own
+ * dividers as part of the IP itself. Because of this, the system clock
+ * rates should not be changed.
+ *
+ * The HCLK PLL is clocked from SYSCLK, which can be derived from the
+ * main oscillator or PLL397. PLL397 generates a rate that is 397 times
+ * the 32KHz oscillator rate. The main oscillator runs at the selected
+ * oscillator/crystal rate on the mosc_in pin of the LPC32xx. This rate
+ * is normally 13MHz, but depends on the selection of external crystals
+ * or oscillators. If USB operation is required, the main oscillator must
+ * be used in the system.
+ *
+ * Switching SYSCLK between sources during normal Linux operation is not
+ * supported. SYSCLK is preset in the bootloader. Because of the
+ * complexities of clock management during clock frequency changes,
+ * there are some limitations to the clock driver explained below:
+ * - The PLL397 and main oscillator can be enabled and disabled by the
+ *   clk_enable() and clk_disable() functions unless SYSCLK is based
+ *   on that clock. This allows the other oscillator that isn't driving
+ *   the HCLK PLL to be used as another system clock that can be routed
+ *   to an external pin.
+ * - The muxed SYSCLK input and HCLK_PLL rate cannot be changed with
+ *   this driver.
+ * - HCLK and PCLK rates cannot be changed as part of this driver.
+ * - Most peripherals have their own dividers are part of the peripheral
+ *   block. Changing SYSCLK, HCLK PLL, HCLK, or PCLK sources or rates
+ *   will also impact the individual peripheral rates.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+
+#include <mach/hardware.h>
+#include <asm/clkdev.h>
+#include <mach/clkdev.h>
+#include <mach/platform.h>
+#include "clock.h"
+#include "common.h"
+
+static struct clk clk_armpll;
+static struct clk clk_usbpll;
+static struct mutex clkm_lock;
+
+/*
+ * Post divider values for PLLs based on selected register value
+ */
+const u32 pll_postdivs[4] = {1, 2, 4, 8};
+
+static u32 local_return_parent_rate(struct clk *clk)
+{
+	/*
+	 * If a clock has a rate of 0, then it inherits it's parent
+	 * clock rate
+	 */
+	if (clk->rate == 0)
+		return local_return_parent_rate(clk->parent);
+
+	return clk->rate;
+}
+
+/* 32KHz clock has a fixed rate and is not stoppable */
+static struct clk osc_32KHz = {
+	.rate		= LPC32XX_CLOCK_OSC_FREQ,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static int local_pll397_enable(struct clk *clk, int enable)
+{
+	u32 reg;
+	unsigned long timeout = 1 + msecs_to_jiffies(10);
+
+	reg = __raw_readl(LPC32XX_CLKPWR_PLL397_CTRL);
+
+	if (enable == 0) 	{
+		reg |= LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS;
+		__raw_writel(reg, LPC32XX_CLKPWR_PLL397_CTRL);
+		clk->rate = 0;
+	} else {
+		/* Enable PLL397 */
+		reg &= ~LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS;
+		__raw_writel(reg, LPC32XX_CLKPWR_PLL397_CTRL);
+		clk->rate = LPC32XX_CLOCK_OSC_FREQ * 397;
+
+		/* Wait for PLL397 lock */
+		while (((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) &
+			LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0) &&
+			(timeout > jiffies))
+			cpu_relax();
+
+		if ((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) &
+			LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0)
+			return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int local_oscmain_enable(struct clk *clk, int enable)
+{
+	u32 reg;
+	unsigned long timeout = 1 + msecs_to_jiffies(10);
+
+	reg = __raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL);
+
+	if (enable == 0) {
+		reg |= LPC32XX_CLKPWR_MOSC_DISABLE;
+		__raw_writel(reg, LPC32XX_CLKPWR_MAIN_OSC_CTRL);
+		clk->rate = 0;
+	} else {
+		/* Enable main oscillator */
+		reg &= ~LPC32XX_CLKPWR_MOSC_DISABLE;
+		__raw_writel(reg, LPC32XX_CLKPWR_MAIN_OSC_CTRL);
+		clk->rate = LPC32XX_MAIN_OSC_FREQ;
+
+		/* Wait for main oscillator to start */
+		while (((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) &
+			LPC32XX_CLKPWR_MOSC_DISABLE) != 0) &&
+			(timeout > jiffies))
+			cpu_relax();
+
+		if ((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) &
+			LPC32XX_CLKPWR_MOSC_DISABLE) != 0)
+			return -ENODEV;
+	}
+
+	return 0;
+}
+
+static struct clk osc_pll397 = {
+	.parent		= &osc_32KHz,
+	.enable		= &local_pll397_enable,
+	.rate		= LPC32XX_CLOCK_OSC_FREQ * 397,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk osc_main = {
+	.enable		= &local_oscmain_enable,
+	.rate		= LPC32XX_MAIN_OSC_FREQ,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_sys;
+
+/*
+ * Setup the HCLK PLL with a PLL structure
+ */
+static u32 local_clk_pll_setup(struct clk_pll_setup *PllSetup)
+{
+	u32 tv, tmp = 0;
+
+	if (PllSetup->analog_on != 0)
+		tmp |= LPC32XX_CLKPWR_HCLKPLL_POWER_UP;
+	if (PllSetup->cco_bypass_b15 != 0)
+		tmp |= LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS;
+	if (PllSetup->direct_output_b14 != 0)
+		tmp |= LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS;
+	if (PllSetup->fdbk_div_ctrl_b13 != 0)
+		tmp |= LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK;
+
+	switch (PllSetup->pll_p) {
+	case 1:
+		tv = 0;
+		break;
+
+	case 2:
+		tv = 1;
+		break;
+
+	case 4:
+		tv = 2;
+		break;
+
+	case 8:
+		tv = 3;
+		break;
+
+	default:
+		return 0;
+	}
+
+	tmp |= LPC32XX_CLKPWR_HCLKPLL_POSTDIV_2POW(tv);
+	tmp |= LPC32XX_CLKPWR_HCLKPLL_PREDIV_PLUS1(PllSetup->pll_n - 1);
+	tmp |= LPC32XX_CLKPWR_HCLKPLL_PLLM(PllSetup->pll_m - 1);
+
+	return tmp;
+}
+
+/*
+ * Update the ARM core PLL frequency rate variable from the actual PLL setting
+ */
+static void local_update_armpll_rate(void)
+{
+	u32 clkin, pllreg;
+
+	clkin = clk_armpll.parent->rate;
+	pllreg = __raw_readl(LPC32XX_CLKPWR_HCLKPLL_CTRL) & 0x1FFFF;
+
+	clk_armpll.rate = clk_get_pllrate_from_reg(clkin, pllreg);
+}
+
+/*
+ * Find a PLL configuration for the selected input frequency
+ */
+static u32 local_clk_find_pll_cfg(u32 pllin_freq, u32 target_freq,
+	struct clk_pll_setup *pllsetup)
+{
+	u32 ifreq, freqtol, m, n, p, fclkout;
+
+	/* Determine frequency tolerance limits */
+	freqtol = target_freq / 250;
+	ifreq = pllin_freq;
+
+	/* Is direct bypass mode possible? */
+	if (abs(pllin_freq - target_freq) <= freqtol) {
+		pllsetup->analog_on = 0;
+		pllsetup->cco_bypass_b15 = 1;
+		pllsetup->direct_output_b14 = 1;
+		pllsetup->fdbk_div_ctrl_b13 = 1;
+		pllsetup->pll_p = pll_postdivs[0];
+		pllsetup->pll_n = 1;
+		pllsetup->pll_m = 1;
+		return clk_check_pll_setup(ifreq, pllsetup);
+	} else if (target_freq <= ifreq) {
+		pllsetup->analog_on = 0;
+		pllsetup->cco_bypass_b15 = 1;
+		pllsetup->direct_output_b14 = 0;
+		pllsetup->fdbk_div_ctrl_b13 = 1;
+		pllsetup->pll_n = 1;
+		pllsetup->pll_m = 1;
+		for (p = 0; p <= 3; p++) {
+			pllsetup->pll_p = pll_postdivs[p];
+			fclkout = clk_check_pll_setup(ifreq, pllsetup);
+			if (abs(target_freq - fclkout) <= freqtol)
+				return fclkout;
+		}
+	}
+
+	/* Is direct mode possible? */
+	pllsetup->analog_on = 1;
+	pllsetup->cco_bypass_b15 = 0;
+	pllsetup->direct_output_b14 = 1;
+	pllsetup->fdbk_div_ctrl_b13 = 0;
+	pllsetup->pll_p = pll_postdivs[0];
+	for (m = 1; m <= 256; m++) {
+		for (n = 1; n <= 4; n++) {
+			/* Compute output frequency for this value */
+			pllsetup->pll_n = n;
+			pllsetup->pll_m = m;
+			fclkout = clk_check_pll_setup(ifreq,
+				pllsetup);
+			if (abs(target_freq - fclkout) <=
+				freqtol)
+				return fclkout;
+		}
+	}
+
+	/* Is integer mode possible? */
+	pllsetup->analog_on = 1;
+	pllsetup->cco_bypass_b15 = 0;
+	pllsetup->direct_output_b14 = 0;
+	pllsetup->fdbk_div_ctrl_b13 = 1;
+	for (m = 1; m <= 256; m++) {
+		for (n = 1; n <= 4; n++) {
+			for (p = 0; p < 4; p++) {
+				/* Compute output frequency */
+				pllsetup->pll_p = pll_postdivs[p];
+				pllsetup->pll_n = n;
+				pllsetup->pll_m = m;
+				fclkout = clk_check_pll_setup(
+					ifreq, pllsetup);
+				if (abs(target_freq - fclkout) <= freqtol)
+					return fclkout;
+			}
+		}
+	}
+
+	/* Try non-integer mode */
+	pllsetup->analog_on = 1;
+	pllsetup->cco_bypass_b15 = 0;
+	pllsetup->direct_output_b14 = 0;
+	pllsetup->fdbk_div_ctrl_b13 = 0;
+	for (m = 1; m <= 256; m++) {
+		for (n = 1; n <= 4; n++) {
+			for (p = 0; p < 4; p++) {
+				/* Compute output frequency */
+				pllsetup->pll_p = pll_postdivs[p];
+				pllsetup->pll_n = n;
+				pllsetup->pll_m = m;
+				fclkout = clk_check_pll_setup(
+					ifreq, pllsetup);
+				if (abs(target_freq - fclkout) <= freqtol)
+					return fclkout;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static struct clk clk_armpll = {
+	.parent		= &clk_sys,
+	.get_rate	= &local_return_parent_rate,
+};
+
+/*
+ * Update the USB PLL frequency rate variable from the actual PLL setting
+ */
+static void local_update_usbpll_rate(void)
+{
+	u32 clkin, pllreg;
+
+	clkin = clk_usbpll.get_rate(&clk_usbpll);
+	pllreg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL) & 0x1FFFF;
+
+	if ((pllreg & LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP) == 0)
+		clk_usbpll.rate = 0;
+	else
+		clk_usbpll.rate = clk_get_pllrate_from_reg(clkin,
+			pllreg);
+}
+
+/*
+ * Setup the USB PLL with a PLL structure
+ */
+static u32 local_clk_usbpll_setup(struct clk_pll_setup *pHCLKPllSetup)
+{
+	u32 reg, tmp = local_clk_pll_setup(pHCLKPllSetup);
+
+	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL) & ~0x1FFFF;
+	reg |= tmp;
+	__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+
+	return clk_check_pll_setup(clk_usbpll.parent->rate,
+		pHCLKPllSetup);
+}
+
+static int local_usbpll_enable(struct clk *clk, int enable)
+{
+	u32 reg;
+	int ret = -ENODEV;
+	unsigned long timeout = 1 + msecs_to_jiffies(10);
+
+	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
+
+	if (enable == 0) {
+		reg &= ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 |
+			LPC32XX_CLKPWR_USBCTRL_CLK_EN2);
+		__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+	} else if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP) {
+		reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1;
+		__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+
+		/* Wait for PLL lock */
+		while ((timeout > jiffies) & (ret == -ENODEV)) {
+			reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
+			if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS)
+				ret = 0;
+		}
+
+		if (ret == 0) {
+			reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2;
+			__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+		}
+	}
+
+	return ret;
+}
+
+static int local_usbpll_set_rate(struct clk *clk, u32 rate)
+{
+	u32 clkin, reg, usbdiv;
+	struct clk_pll_setup pllsetup;
+
+	/*
+	 * Unlike other clocks, this clock has a KHz input rate, so bump
+	 * it up to work with the PLL function
+	 */
+	rate = rate * 1000;
+
+	local_usbpll_enable(clk, 0);
+
+	if (rate == 0)
+		return 0;
+
+	clkin = clk->parent->rate;
+	usbdiv = __raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) + 1;
+	clkin = clkin / usbdiv;
+
+	/* Try to find a good rate setup */
+	if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0)
+		return -EINVAL;
+
+	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
+	reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1;
+	__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+
+	pllsetup.analog_on = 1;
+	local_clk_usbpll_setup(&pllsetup);
+
+	clk->rate = clk_check_pll_setup(clkin, &pllsetup);
+
+	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
+	reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2;
+	__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
+
+	return 0;
+}
+
+static struct clk clk_usbpll = {
+	.parent		= &osc_main,
+	.set_rate	= &local_usbpll_set_rate,
+	.enable		= &local_usbpll_enable,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static u32 clk_get_hclk_div(void)
+{
+	static const u32 hclkdivs[4] = {1, 2, 4, 4};
+	return hclkdivs[LPC32XX_CLKPWR_HCLKDIV_DIV_2POW(
+		__raw_readl(LPC32XX_CLKPWR_HCLK_DIV))];
+}
+
+static struct clk clk_hclk = {
+	.parent		= &clk_armpll,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_pclk = {
+	.parent		= &clk_armpll,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static int local_onoff_enable(struct clk *clk, int enable)
+{
+	u32 tmp;
+
+	tmp = __raw_readl(clk->enable_reg);
+
+	if (enable == 0)
+		tmp &= ~clk->enable_mask;
+	else
+		tmp |= clk->enable_mask;
+
+	__raw_writel(tmp, clk->enable_reg);
+
+	return 0;
+}
+
+/* Peripheral clock sources */
+static struct clk clk_timer0 = {
+	.parent		= &clk_pclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
+	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+static struct clk clk_timer1 = {
+	.parent		= &clk_pclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
+	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+static struct clk clk_timer2 = {
+	.parent		= &clk_pclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
+	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER2_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+static struct clk clk_timer3 = {
+	.parent		= &clk_pclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
+	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER3_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+static struct clk clk_wdt = {
+	.parent		= &clk_pclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_TIMER_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_PWMCLK_WDOG_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+static struct clk clk_vfp9 = {
+	.parent		= &clk_pclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_DEBUG_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_VFP_CLOCK_ENABLE_BIT,
+	.get_rate	= &local_return_parent_rate,
+};
+static struct clk clk_dma = {
+	.parent		= &clk_hclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_DMA_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_uart3 = {
+	.parent		= &clk_pclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART3_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_uart4 = {
+	.parent		= &clk_pclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART4_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_uart5 = {
+	.parent		= &clk_pclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART5_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_uart6 = {
+	.parent		= &clk_pclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART6_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_i2c0 = {
+	.parent		= &clk_hclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_I2C_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_I2CCLK_I2C1CLK_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_i2c1 = {
+	.parent		= &clk_hclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_I2C_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_I2CCLK_I2C2CLK_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_i2c2 = {
+	.parent		= &clk_pclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= io_p2v(LPC32XX_USB_BASE + 0xFF4),
+	.enable_mask	= 0x4,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_ssp0 = {
+	.parent		= &clk_hclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_SSP_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_ssp1 = {
+	.parent		= &clk_hclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_SSP_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_SSPCTRL_SSPCLK1_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_kscan = {
+	.parent		= &osc_32KHz,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_KEY_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_KEYCLKCTRL_CLK_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_nand = {
+	.parent		= &clk_hclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_NAND_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_i2s0 = {
+	.parent		= &clk_hclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_I2S_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_I2SCTRL_I2SCLK0_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_i2s1 = {
+	.parent		= &clk_hclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_I2S_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_net = {
+	.parent		= &clk_hclk,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_MACCLK_CTRL,
+	.enable_mask	= (LPC32XX_CLKPWR_MACCTRL_DMACLK_EN |
+		LPC32XX_CLKPWR_MACCTRL_MMIOCLK_EN |
+		LPC32XX_CLKPWR_MACCTRL_HRCCLK_EN),
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_rtc = {
+	.parent		= &osc_32KHz,
+	.rate		= 1, /* 1 Hz */
+	.get_rate	= &local_return_parent_rate,
+};
+
+static struct clk clk_usbd = {
+	.parent		= &clk_usbpll,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_USB_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_USBCTRL_HCLK_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static int tsc_onoff_enable(struct clk *clk, int enable)
+{
+	u32 tmp;
+
+	/* Make sure 32KHz clock is the selected clock */
+	tmp = __raw_readl(LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
+	tmp &= ~LPC32XX_CLKPWR_ADCCTRL1_PCLK_SEL;
+	__raw_writel(tmp, LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
+
+	if (enable == 0)
+		__raw_writel(0, clk->enable_reg);
+	else
+		__raw_writel(clk->enable_mask, clk->enable_reg);
+
+	return 0;
+}
+
+static struct clk clk_tsc = {
+	.parent		= &osc_32KHz,
+	.enable		= &tsc_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_ADC_CLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_ADC32CLKCTRL_CLK_EN,
+	.get_rate	= &local_return_parent_rate,
+};
+
+static int mmc_onoff_enable(struct clk *clk, int enable)
+{
+	u32 tmp;
+
+	tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) &
+		~(LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
+		LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(15));
+
+	/* If rate is 0, disable clock */
+	if (enable != 0)
+		tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
+			LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(1);
+
+	__raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
+
+	return 0;
+}
+
+static u32 mmc_get_rate(struct clk *clk)
+{
+	u32 div, tmp, rate;
+
+	div = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
+	tmp = div & LPC32XX_CLKPWR_MSCARD_SDCARD_EN;
+
+	if (!tmp)
+		return 0;
+
+	/* Get the parent clock rate */
+	rate = clk->parent->get_rate(clk->parent);
+
+	/* Get the LCD controller clock divider value */
+	div = div & 0xF;
+
+	if (!div)
+		return 0;
+
+	tmp = rate / div;
+
+	return tmp;
+}
+
+static int mmc_set_rate(struct clk *clk, u32 rate)
+{
+	if (rate == 0)
+		mmc_onoff_enable(clk, 0);
+	else
+		mmc_onoff_enable(clk, 1);
+
+	return 0;
+}
+
+static struct clk clk_mmc = {
+	.parent		= &clk_armpll,
+	.set_rate	= &mmc_set_rate,
+	.get_rate	= &mmc_get_rate,
+	.enable		= &mmc_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_MS_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_MSCARD_SDCARD_EN,
+};
+
+static u32 clcd_get_rate(struct clk *clk)
+{
+	u32 tmp, div, rate;
+
+	tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) &
+		LPC32XX_CLKPWR_LCDCTRL_CLK_EN;
+
+	if (!tmp)
+		return 0;
+
+	rate = clk->parent->get_rate(clk->parent);
+	tmp = __raw_readl(io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2));
+
+	/* Only supports internal clocking */
+	if (tmp & TIM2_BCD)
+		return rate;
+
+	div = (tmp & 0x1F) | ((tmp & 0xF8) >> 22);
+	tmp = rate / (2 + div);
+
+	return tmp;
+}
+
+static int clcd_set_rate(struct clk *clk, u32 rate)
+{
+	u32 tmp, prate, div;
+
+	tmp = __raw_readl(io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2));
+	prate = clk->parent->get_rate(clk->parent);
+
+	if (rate == prate) {
+		tmp |= TIM2_BCD;
+		local_onoff_enable(clk, 1);
+	} else {
+		/* Find closest divider */
+		div = prate / rate;
+		if (div == 1)
+			div = 0;
+		else
+			div -= 2;
+
+		tmp &= ~(0xF800001F);
+		tmp &= ~TIM2_BCD;
+		tmp |= (div & 0x1F);
+		tmp |= (((div >> 5) & 0x1F) << 27);
+		__raw_writel(tmp, io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2));
+		local_onoff_enable(clk, 1);
+	}
+
+	return 0;
+}
+
+static struct clk clk_lcd = {
+	.parent		= &clk_hclk,
+	.set_rate	= &clcd_set_rate,
+	.get_rate	= &clcd_get_rate,
+	.enable		= &local_onoff_enable,
+	.enable_reg	= LPC32XX_CLKPWR_LCDCLK_CTRL,
+	.enable_mask	= LPC32XX_CLKPWR_LCDCTRL_CLK_EN,
+};
+
+static inline void clk_lock(void)
+{
+	mutex_lock(&clkm_lock);
+}
+
+static inline void clk_unlock(void)
+{
+	mutex_unlock(&clkm_lock);
+}
+
+static void local_clk_disable(struct clk *clk)
+{
+	/* Don't attempt to disable clock if it has no users */
+	if (clk->usecount > 0) {
+		clk->usecount--;
+
+		/* Only disable clock when it has no more users */
+		if ((clk->usecount == 0) && (clk->enable))
+			clk->enable(clk, 0);
+
+		/* Check parent clocks, they may need to be disabled too */
+		if (clk->parent)
+			local_clk_disable(clk->parent);
+	}
+}
+
+static int local_clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (clk->usecount == 0) {
+		/* Enable parent clocks first */
+		if (clk->parent)
+			ret = local_clk_enable(clk->parent);
+
+		/* Enable clock on first use */
+		if ((ret == 0) && (clk->enable)) {
+			ret = clk->enable(clk, 1);
+			clk->usecount++;
+		}
+
+		/* Back out use counters if enable fails */
+		if (ret < 0)
+			local_clk_disable(clk);
+	}
+
+	return ret;
+}
+
+/*
+ * clk_enable - inform the system when the clock source should be running.
+ */
+int clk_enable(struct clk *clk)
+{
+	int ret;
+
+	clk_lock();
+	ret = local_clk_enable(clk);
+	clk_unlock();
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_enable);
+
+/*
+ * clk_disable - inform the system when the clock source is no longer required
+ */
+void clk_disable(struct clk *clk)
+{
+	clk_lock();
+	local_clk_disable(clk);
+	clk_unlock();
+}
+EXPORT_SYMBOL(clk_disable);
+
+/*
+ * clk_get_rate - obtain the current clock rate (in Hz) for a clock source
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+	unsigned long rate;
+
+	clk_lock();
+	rate = (clk->get_rate)(clk);
+	clk_unlock();
+
+	return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+/*
+ * clk_set_rate - set the clock rate for a clock source
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	int ret = -EINVAL;
+
+	/*
+	 * Most system clocks can only be enabled or disabled, with
+	 * the actual rate set as part of the peripheral dividers
+	 * instead of high level clock control
+	 */
+	if (clk->set_rate) {
+		clk_lock();
+		ret = (clk->set_rate)(clk, rate);
+		clk_unlock();
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+/*
+ * clk_round_rate - adjust a rate to the exact rate a clock can provide
+ */
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+	int ret;
+
+	/* Use set_rate to try to adjust the rate if it supports it */
+	ret = clk_set_rate(clk, rate);
+	if (ret < 0)
+		return ret;
+
+	return clk->rate;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+/*
+ * clk_set_parent - set the parent clock source for this clock
+ */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+	/* Clock re-parenting is not supported */
+	return -EINVAL;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+/*
+ * clk_get_parent - get the parent clock source for this clock
+ */
+struct clk *clk_get_parent(struct clk *clk)
+{
+	return clk->parent;
+}
+EXPORT_SYMBOL(clk_get_parent);
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = (d), \
+		.con_id = (n), \
+		.clk = &(c), \
+	},
+
+static struct clk_lookup lookups[] = {
+	_REGISTER_CLOCK(NULL, "osc_32KHz", osc_32KHz)
+	_REGISTER_CLOCK(NULL, "osc_pll397", osc_pll397)
+	_REGISTER_CLOCK(NULL, "osc_main", osc_main)
+	_REGISTER_CLOCK(NULL, "sys_ck", clk_sys)
+	_REGISTER_CLOCK(NULL, "arm_pll_ck", clk_armpll)
+	_REGISTER_CLOCK(NULL, "ck_pll5", clk_usbpll)
+	_REGISTER_CLOCK(NULL, "hclk_ck", clk_hclk)
+	_REGISTER_CLOCK(NULL, "pclk_ck", clk_pclk)
+	_REGISTER_CLOCK(NULL, "timer0_ck", clk_timer0)
+	_REGISTER_CLOCK(NULL, "timer1_ck", clk_timer1)
+	_REGISTER_CLOCK(NULL, "timer2_ck", clk_timer2)
+	_REGISTER_CLOCK(NULL, "timer3_ck", clk_timer3)
+	_REGISTER_CLOCK(NULL, "vfp9_ck", clk_vfp9)
+	_REGISTER_CLOCK(NULL, "clk_dmac", clk_dma)
+	_REGISTER_CLOCK("pnx4008-watchdog", NULL, clk_wdt)
+	_REGISTER_CLOCK(NULL, "uart3_ck", clk_uart3)
+	_REGISTER_CLOCK(NULL, "uart4_ck", clk_uart4)
+	_REGISTER_CLOCK(NULL, "uart5_ck", clk_uart5)
+	_REGISTER_CLOCK(NULL, "uart6_ck", clk_uart6)
+	_REGISTER_CLOCK("pnx-i2c.0", NULL, clk_i2c0)
+	_REGISTER_CLOCK("pnx-i2c.1", NULL, clk_i2c1)
+	_REGISTER_CLOCK("pnx-i2c.2", NULL, clk_i2c2)
+	_REGISTER_CLOCK("dev:ssp0", NULL, clk_ssp0)
+	_REGISTER_CLOCK("dev:ssp1", NULL, clk_ssp1)
+	_REGISTER_CLOCK("lpc32xx_keys.0", NULL, clk_kscan)
+	_REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand)
+	_REGISTER_CLOCK("tbd", "i2s0_ck", clk_i2s0)
+	_REGISTER_CLOCK("tbd", "i2s1_ck", clk_i2s1)
+	_REGISTER_CLOCK("lpc32xx-ts", NULL, clk_tsc)
+	_REGISTER_CLOCK("dev:mmc0", "MCLK", clk_mmc)
+	_REGISTER_CLOCK("lpc-net.0", NULL, clk_net)
+	_REGISTER_CLOCK("dev:clcd", NULL, clk_lcd)
+	_REGISTER_CLOCK("lpc32xx_udc", "ck_usbd", clk_usbd)
+	_REGISTER_CLOCK("lpc32xx_rtc", NULL, clk_rtc)
+};
+
+static int __init clk_init(void)
+{
+	int i;
+
+	mutex_init(&clkm_lock);
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
+
+	/*
+	 * Setup muxed SYSCLK for HCLK PLL base -this selects the
+	 * parent clock used for the ARM PLL and is used to derive
+	 * the many system clock rates in the device.
+	 */
+	if (clk_is_sysclk_mainosc() != 0)
+		clk_sys.parent = &osc_main;
+	else
+		clk_sys.parent = &osc_pll397;
+
+	clk_sys.rate = clk_sys.parent->rate;
+
+	/* Compute the current ARM PLL and USB PLL frequencies */
+	local_update_armpll_rate();
+	local_update_usbpll_rate();
+
+	/* Compute HCLK and PCLK bus rates */
+	clk_hclk.rate = clk_hclk.parent->rate / clk_get_hclk_div();
+	clk_pclk.rate = clk_pclk.parent->rate / clk_get_pclk_div();
+
+	/*
+	 * Enable system clocks - this step is somewhat formal, as the
+	 * clocks are already running, but it does get the clock data
+	 * inline with the actual system state. Never disable these
+	 * clocks as they will only stop if the system is going to sleep.
+	 * In that case, the chip/system power management functions will
+	 * handle clock gating.
+	 */
+	clk_enable(&clk_hclk);
+	clk_enable(&clk_pclk);
+
+	/*
+	 * Timers 0 and 1 were enabled and are being used by the high
+	 * resolution tick function prior to this driver being initialized.
+	 * Tag them now as used.
+	 */
+	clk_enable(&clk_timer0);
+	clk_enable(&clk_timer1);
+
+	return 0;
+}
+core_initcall(clk_init);
+
diff --git a/arch/arm/mach-lpc32xx/clock.h b/arch/arm/mach-lpc32xx/clock.h
new file mode 100644
index 0000000..97789b9
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/clock.h
@@ -0,0 +1,37 @@
+/*
+ * arch/arm/mach-lpc32xx/clock.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LPC32XX_CLOCK_H
+#define __LPC32XX_CLOCK_H
+
+struct clk {
+	struct list_head node;
+	struct clk *parent;
+	u32 rate;
+	s8 usecount;
+
+	int (*set_rate) (struct clk *, u32);
+	int (*enable) (struct clk *clk, int);
+	u32 (*get_rate) (struct clk *clk);
+
+	/* Register address and bit mask for simple clocks */
+	void __iomem *enable_reg;
+	u32 enable_mask;
+};
+
+#endif
-- 
1.6.6

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

* [PATCH 04/14] ARM: LPC32XX: GPIO, timer, and IRQ drivers
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
                   ` (2 preceding siblings ...)
  2010-02-09  0:11 ` [PATCH 03/14] ARM: LPC32XX: Clock driver wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-09 10:58   ` Uwe Kleine-König
  2010-02-09  0:11 ` [PATCH 05/14] ARM: LPC32XX: System suspend support wellsk40 at gmail.com
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

Common drivers for the LPC32XX used on all platforms

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 arch/arm/mach-lpc32xx/gpiolib.c |  458 +++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-lpc32xx/irq.c     |  438 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-lpc32xx/timer.c   |  182 ++++++++++++++++
 3 files changed, 1078 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-lpc32xx/gpiolib.c b/arch/arm/mach-lpc32xx/gpiolib.c
new file mode 100644
index 0000000..202cd82
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/gpiolib.c
@@ -0,0 +1,458 @@
+/*
+ * arch/arm/mach-lpc32xx/gpiolib.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+
+#define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000)
+#define LPC32XX_GPIO_P3_OUTP_SET		_GPREG(0x004)
+#define LPC32XX_GPIO_P3_OUTP_CLR		_GPREG(0x008)
+#define LPC32XX_GPIO_P3_OUTP_STATE		_GPREG(0x00C)
+#define LPC32XX_GPIO_P2_DIR_SET			_GPREG(0x010)
+#define LPC32XX_GPIO_P2_DIR_CLR			_GPREG(0x014)
+#define LPC32XX_GPIO_P2_DIR_STATE		_GPREG(0x018)
+#define LPC32XX_GPIO_P2_INP_STATE		_GPREG(0x01C)
+#define LPC32XX_GPIO_P2_OUTP_SET		_GPREG(0x020)
+#define LPC32XX_GPIO_P2_OUTP_CLR		_GPREG(0x024)
+#define LPC32XX_GPIO_P2_MUX_SET			_GPREG(0x028)
+#define LPC32XX_GPIO_P2_MUX_CLR			_GPREG(0x02C)
+#define LPC32XX_GPIO_P2_MUX_STATE		_GPREG(0x030)
+#define LPC32XX_GPIO_P0_INP_STATE		_GPREG(0x040)
+#define LPC32XX_GPIO_P0_OUTP_SET		_GPREG(0x044)
+#define LPC32XX_GPIO_P0_OUTP_CLR		_GPREG(0x048)
+#define LPC32XX_GPIO_P0_OUTP_STATE		_GPREG(0x04C)
+#define LPC32XX_GPIO_P0_DIR_SET			_GPREG(0x050)
+#define LPC32XX_GPIO_P0_DIR_CLR			_GPREG(0x054)
+#define LPC32XX_GPIO_P0_DIR_STATE		_GPREG(0x058)
+#define LPC32XX_GPIO_P1_INP_STATE		_GPREG(0x060)
+#define LPC32XX_GPIO_P1_OUTP_SET		_GPREG(0x064)
+#define LPC32XX_GPIO_P1_OUTP_CLR		_GPREG(0x068)
+#define LPC32XX_GPIO_P1_OUTP_STATE		_GPREG(0x06C)
+#define LPC32XX_GPIO_P1_DIR_SET			_GPREG(0x070)
+#define LPC32XX_GPIO_P1_DIR_CLR			_GPREG(0x074)
+#define LPC32XX_GPIO_P1_DIR_STATE		_GPREG(0x078)
+
+#define GPIO012_PIN_TO_BIT(x)			(1 << (x))
+#define GPIO3_PIN_TO_BIT(x)			(1 << ((x) + 25))
+#define GPO3_PIN_TO_BIT(x)			(1 << (x))
+#define GPIO012_PIN_IN_SEL(x, y)		(((x) >> (y)) & 1)
+#define GPIO3_PIN_IN_SEL(x, y)			(((x) >> (10 + (y))) & 1)
+#define GPIO3_PIN5_IN_SEL(x)			(((x) >> 24) & 1)
+#define GPI3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
+
+struct gpio_regs {
+	void __iomem *inp_state;
+	void __iomem *outp_set;
+	void __iomem *outp_clr;
+	void __iomem *dir_set;
+	void __iomem *dir_clr;
+};
+
+/*
+ * GPIO names
+ */
+static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {
+	"p0.0", "p0.1", "p0.2", "p0.3",
+	"p0.4", "p0.5", "p0.6", "p0.7"
+};
+
+static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {
+	"p1.0", "p1.1", "p1.2", "p1.3",
+	"p1.4", "p1.5", "p1.6", "p1.7",
+	"p1.8", "p1.9", "p1.10", "p1.11",
+	"p1.12", "p1.13", "p1.14", "p1.15",
+	"p1.16", "p1.17", "p1.18", "p1.19",
+	"p1.20", "p1.21", "p1.22", "p1.23",
+};
+
+static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
+	"p2.0", "p2.1", "p2.2", "p2.3",
+	"p2.4", "p2.5", "p2.6", "p2.7",
+	"p2.8", "p2.9", "p2.10", "p2.11",
+	"p2.12"
+};
+
+static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
+	"gpi000", "gpio01", "gpio02", "gpio03",
+	"gpio04", "gpio05"
+};
+
+static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
+	"gpi00", "gpi01", "gpi02", "gpi03",
+	"gpi04", "gpi05", "gpi06", "gpi07",
+	"gpi08", "gpi09",  NULL,    NULL,
+	 NULL,    NULL,    NULL,   "gpi15",
+	"gpi16", "gpi17", "gpi18", "gpi19",
+	"gpi20", "gpi21", "gpi22", "gpi23",
+	"gpi24", "gpi25", "gpi26", "gpi27"
+};
+
+static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
+	"gpo00", "gpo01", "gpo02", "gpo03",
+	"gpo04", "gpo05", "gpo06", "gpo07",
+	"gpo08", "gpo09", "gpo10", "gpo11",
+	"gpo12", "gpo13", "gpo14", "gpo15",
+	"gpo16", "gpo17", "gpo18", "gpo19",
+	"gpo20", "gpo21", "gpo22", "gpo23"
+};
+
+static struct gpio_regs gpio_grp_regs_p0 = {
+	.inp_state	= LPC32XX_GPIO_P0_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P0_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P0_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P0_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P0_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p1 = {
+	.inp_state	= LPC32XX_GPIO_P1_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P1_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P1_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P1_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P1_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p2 = {
+	.inp_state	= LPC32XX_GPIO_P2_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P2_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P2_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
+};
+
+static struct gpio_regs gpio_grp_regs_p3 = {
+	.inp_state	= LPC32XX_GPIO_P3_INP_STATE,
+	.outp_set	= LPC32XX_GPIO_P3_OUTP_SET,
+	.outp_clr	= LPC32XX_GPIO_P3_OUTP_CLR,
+	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
+	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
+};
+
+struct lpc32xx_gpio_chip {
+	struct gpio_chip	chip;
+	struct gpio_regs	*gpio_grp;
+};
+
+static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio(
+	struct gpio_chip *gpc)
+{
+	return container_of(gpc, struct lpc32xx_gpio_chip, chip);
+}
+
+static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int input)
+{
+	if (input)
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->dir_clr);
+	else
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->dir_set);
+}
+
+static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int input)
+{
+	u32 u;
+
+	/* P3 GPIO pins are offset in the register to pin mapping */
+	u =  GPIO3_PIN_TO_BIT(pin);
+
+	if (input)
+		__raw_writel(u, group->gpio_grp->dir_clr);
+	else
+		__raw_writel(u, group->gpio_grp->dir_set);
+}
+
+static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	if (high)
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->outp_set);
+	else
+		__raw_writel(GPIO012_PIN_TO_BIT(pin),
+			group->gpio_grp->outp_clr);
+}
+
+static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	u32 u;
+
+	/* P3 GPIO pins are offset in the register to pin mapping */
+	u = GPIO3_PIN_TO_BIT(pin);
+
+	if (high)
+		__raw_writel(u, group->gpio_grp->outp_set);
+	else
+		__raw_writel(u, group->gpio_grp->outp_clr);
+}
+
+static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin, int high)
+{
+	if (high)
+		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
+	else
+		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
+}
+
+static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
+		pin);
+}
+
+static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	int state;
+
+	state = __raw_readl(group->gpio_grp->inp_state);
+
+	/*
+	 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
+	 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.
+	 */
+	if (pin == 5)
+		state = GPIO3_PIN5_IN_SEL(state);
+	else
+		state = GPIO3_PIN_IN_SEL(state, pin);
+
+	return state;
+}
+
+static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
+	unsigned pin)
+{
+	return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
+}
+
+/*
+ * GENERIC_GPIO primitives.
+ */
+static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,
+	unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p012(group, pin, 1);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,
+	unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p3(group, pin, 1);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,
+	unsigned pin)
+{
+	return 0;
+}
+
+static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpio_state_p012(group, pin);
+}
+
+static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpio_state_p3(group, pin);
+}
+
+static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	return __get_gpi_state_p3(group, pin);
+}
+
+static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p012(group, pin, 0);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_dir_p3(group, pin, 0);
+
+	return 0;
+}
+
+static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	return 0;
+}
+
+static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_level_p012(group, pin, value);
+}
+
+static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpio_level_p3(group, pin, value);
+}
+
+static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
+	int value)
+{
+	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+	__set_gpo_level_p3(group, pin, value);
+}
+
+static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
+{
+	if (pin < chip->ngpio)
+		return 0;
+
+	return -EINVAL;
+}
+
+static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
+	{
+		.chip = {
+			.label			= "gpio_p0",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P0_GRP,
+			.ngpio			= LPC32XX_GPIO_P0_MAX,
+			.names			= gpio_p0_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p0,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p1",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P1_GRP,
+			.ngpio			= LPC32XX_GPIO_P1_MAX,
+			.names			= gpio_p1_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p1,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p2",
+			.direction_input	= lpc32xx_gpio_dir_input_p012,
+			.get			= lpc32xx_gpio_get_value_p012,
+			.direction_output	= lpc32xx_gpio_dir_output_p012,
+			.set			= lpc32xx_gpio_set_value_p012,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P2_GRP,
+			.ngpio			= LPC32XX_GPIO_P2_MAX,
+			.names			= gpio_p2_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p2,
+	},
+	{
+		.chip = {
+			.label			= "gpio_p3",
+			.direction_input	= lpc32xx_gpio_dir_input_p3,
+			.get			= lpc32xx_gpio_get_value_p3,
+			.direction_output	= lpc32xx_gpio_dir_output_p3,
+			.set			= lpc32xx_gpio_set_value_p3,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPIO_P3_GRP,
+			.ngpio			= LPC32XX_GPIO_P3_MAX,
+			.names			= gpio_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+	{
+		.chip = {
+			.label			= "gpi_p3",
+			.direction_input	= lpc32xx_gpio_dir_in_always,
+			.get			= lpc32xx_gpi_get_value,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPI_P3_GRP,
+			.ngpio			= LPC32XX_GPI_P3_MAX,
+			.names			= gpi_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+	{
+		.chip = {
+			.label			= "gpo_p3",
+			.direction_output	= lpc32xx_gpio_dir_out_always,
+			.set			= lpc32xx_gpo_set_value,
+			.request		= lpc32xx_gpio_request,
+			.base			= LPC32XX_GPO_P3_GRP,
+			.ngpio			= LPC32XX_GPO_P3_MAX,
+			.names			= gpo_p3_names,
+			.can_sleep		= 0,
+		},
+		.gpio_grp = &gpio_grp_regs_p3,
+	},
+};
+
+void __init lpc32xx_gpio_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++)
+		gpiochip_add(&lpc32xx_gpiochip[i].chip);
+}
diff --git a/arch/arm/mach-lpc32xx/irq.c b/arch/arm/mach-lpc32xx/irq.c
new file mode 100644
index 0000000..18c3caf
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/irq.c
@@ -0,0 +1,438 @@
+/*
+ * arch/arm/mach-lpc32xx/irq.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+
+/*
+ * Default value representing the Activation polarity of all internal
+ * interrupt sources
+ */
+#define MIC_APR_DEFAULT		0x3FF0EFE0
+#define SIC1_APR_DEFAULT	0xFBD27186
+#define SIC2_APR_DEFAULT	0x801810C0
+
+/*
+ * Default value representing the Activation Type of all internal
+ * interrupt sources. All are level sensitive.
+ */
+#define MIC_ATR_DEFAULT		0x00000000
+#define SIC1_ATR_DEFAULT	0x00026000
+#define SIC2_ATR_DEFAULT	0x00000000
+
+struct lpc32xx_event_group_regs {
+	void __iomem *enab_reg;
+	void __iomem *edge_reg;
+	void __iomem *maskstat_reg;
+	void __iomem *rawstat_reg;
+};
+
+static const struct lpc32xx_event_group_regs lpc32xx_event_int_regs = {
+	.enab_reg = LPC32XX_CLKPWR_INT_ER,
+	.edge_reg = LPC32XX_CLKPWR_INT_AP,
+	.maskstat_reg = LPC32XX_CLKPWR_INT_SR,
+	.rawstat_reg = LPC32XX_CLKPWR_INT_RS,
+};
+
+static const struct lpc32xx_event_group_regs lpc32xx_event_pin_regs = {
+	.enab_reg = LPC32XX_CLKPWR_PIN_ER,
+	.edge_reg = LPC32XX_CLKPWR_PIN_AP,
+	.maskstat_reg = LPC32XX_CLKPWR_PIN_SR,
+	.rawstat_reg = LPC32XX_CLKPWR_PIN_RS,
+};
+
+struct lpc32xx_event_info {
+	const struct lpc32xx_event_group_regs *event_group;
+	u32 mask;
+};
+
+/*
+ * Maps an IRQ number to and event mask and register
+ */
+static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
+	[IRQ_LPC32XX_GPI_08] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT,
+	},
+	[IRQ_LPC32XX_GPI_09] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_09_BIT,
+	},
+	[IRQ_LPC32XX_GPI_19] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_19_BIT,
+	},
+	[IRQ_LPC32XX_GPI_07] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT,
+	},
+	[IRQ_LPC32XX_GPI_00] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_00_BIT,
+	},
+	[IRQ_LPC32XX_GPI_01] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_01_BIT,
+	},
+	[IRQ_LPC32XX_GPI_02] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_02_BIT,
+	},
+	[IRQ_LPC32XX_GPI_03] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_03_BIT,
+	},
+	[IRQ_LPC32XX_GPI_04] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_04_BIT,
+	},
+	[IRQ_LPC32XX_GPI_05] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_05_BIT,
+	},
+	[IRQ_LPC32XX_GPI_06] = {
+		.event_group = &lpc32xx_event_pin_regs,
+		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_00] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_01] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_02] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_03] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_04] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT,
+	},
+	[IRQ_LPC32XX_GPIO_05] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT,
+	},
+	[IRQ_LPC32XX_KEY] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_KEY_BIT,
+	},
+	[IRQ_LPC32XX_USB_OTG_ATX] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT,
+	},
+	[IRQ_LPC32XX_USB_HOST] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_USB_BIT,
+	},
+	[IRQ_LPC32XX_RTC] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_RTC_BIT,
+	},
+	[IRQ_LPC32XX_MSTIMER] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT,
+	},
+	[IRQ_LPC32XX_TS_AUX] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT,
+	},
+	[IRQ_LPC32XX_TS_P] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_TS_P_BIT,
+	},
+	[IRQ_LPC32XX_TS_IRQ] = {
+		.event_group = &lpc32xx_event_int_regs,
+		.mask = LPC32XX_CLKPWR_INTSRC_ADC_BIT,
+	},
+};
+
+static void get_controller(unsigned int irq, unsigned int *base,
+	unsigned int *irqbit)
+{
+	if (irq < 32) {
+		*base = LPC32XX_MIC_BASE;
+		*irqbit = 1 << irq;
+	} else if (irq < 64) {
+		*base = LPC32XX_SIC1_BASE;
+		*irqbit = 1 << (irq - 32);
+	} else {
+		*base = LPC32XX_SIC2_BASE;
+		*irqbit = 1 << (irq - 64);
+	}
+}
+
+static void lpc32xx_mask_irq(unsigned int irq)
+{
+	unsigned int reg, ctrl, mask;
+
+	get_controller(irq, &ctrl, &mask);
+
+	reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) & ~mask;
+	__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
+}
+
+static void lpc32xx_unmask_irq(unsigned int irq)
+{
+	unsigned int reg, ctrl, mask;
+
+	get_controller(irq, &ctrl, &mask);
+
+	reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) | mask;
+	__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
+}
+
+static void lpc32xx_ack_irq(unsigned int irq)
+{
+	unsigned int ctrl, mask;
+
+	get_controller(irq, &ctrl, &mask);
+
+	__raw_writel(mask, LPC32XX_INTC_RAW_STAT(ctrl));
+
+	/* Also need to clear pending wake event */
+	if (lpc32xx_events[irq].mask != 0)
+		__raw_writel(lpc32xx_events[irq].mask,
+			lpc32xx_events[irq].event_group->rawstat_reg);
+}
+
+static void __lpc32xx_set_irq_type(unsigned int irq, int use_high_level,
+	int use_edge)
+{
+	unsigned int reg, ctrl, mask;
+
+	get_controller(irq, &ctrl, &mask);
+
+	/* Activation level, high or low */
+	reg = __raw_readl(LPC32XX_INTC_POLAR(ctrl));
+	if (use_high_level)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	__raw_writel(reg, LPC32XX_INTC_POLAR(ctrl));
+
+	/* Activation type, edge or level */
+	reg = __raw_readl(LPC32XX_INTC_ACT_TYPE(ctrl));
+	if (use_edge) {
+		reg |= mask;
+		set_irq_handler(irq, handle_edge_irq);
+	} else {
+		reg &= ~mask;
+		set_irq_handler(irq, handle_level_irq);
+	}
+
+	/* Use same polarity for the wake events */
+	if (lpc32xx_events[irq].mask != 0) {
+		reg = __raw_readl(lpc32xx_events[irq].event_group->edge_reg);
+
+		if (use_high_level)
+			reg |= lpc32xx_events[irq].mask;
+		else
+			reg &= ~lpc32xx_events[irq].mask;
+
+		__raw_writel(reg, lpc32xx_events[irq].event_group->edge_reg);
+	}
+}
+
+static int lpc32xx_set_irq_type(unsigned int irq, unsigned int type)
+{
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		/* Rising edge sensitive */
+		__lpc32xx_set_irq_type(irq, 1, 1);
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		/* Falling edge sensitive */
+		__lpc32xx_set_irq_type(irq, 0, 1);
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		/* Low level sensitive */
+		__lpc32xx_set_irq_type(irq, 0, 0);
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		/* High level sensitive */
+		__lpc32xx_set_irq_type(irq, 1, 0);
+		break;
+
+	/* Other modes are not supported */
+	default:
+		return -EINVAL;
+	}
+
+	/* Ok to use the level handler for all types */
+	set_irq_handler(irq, handle_level_irq);
+
+	return 0;
+}
+
+static int lpc32xx_irq_wake(unsigned int irqno, unsigned int state)
+{
+	unsigned long eventreg;
+
+	if (lpc32xx_events[irqno].mask != 0) {
+		eventreg = __raw_readl(lpc32xx_events[irqno].
+			event_group->enab_reg);
+
+		if (state)
+			eventreg |= lpc32xx_events[irqno].mask;
+		else
+			eventreg &= ~lpc32xx_events[irqno].mask;
+
+		__raw_writel(eventreg,
+			lpc32xx_events[irqno].event_group->enab_reg);
+
+		return 0;
+	}
+
+	/* Clear event */
+	__raw_writel(lpc32xx_events[irqno].mask,
+		lpc32xx_events[irqno].event_group->rawstat_reg);
+
+	return -ENODEV;
+}
+
+static void __init lpc32xx_set_default_mappings(unsigned int apr,
+	unsigned int atr, unsigned int offset)
+{
+	unsigned int i;
+
+	/* Set activation levels for each interrupt */
+	i = 0;
+	while (i < 32) {
+		__lpc32xx_set_irq_type(offset + i, ((apr >> i) & 0x1),
+			((atr >> i) & 0x1));
+		i++;
+	}
+}
+
+static struct irq_chip lpc32xx_irq_chip = {
+	.ack = lpc32xx_ack_irq,
+	.mask = lpc32xx_mask_irq,
+	.unmask = lpc32xx_unmask_irq,
+	.set_type = lpc32xx_set_irq_type,
+	.set_wake = lpc32xx_irq_wake
+};
+
+#define SIC1_IRQ(x) ((x) + 32)
+#define SIC2_IRQ(x) ((x) + 64)
+
+static void lpc32xx_sic1_handler(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC1_BASE));
+
+	while (ints != 0) {
+		int irqno = fls(ints) - 1;
+
+		ints &= ~(1 << irqno);
+
+		handle_level_irq(SIC1_IRQ(irqno), desc);
+	}
+}
+
+static void lpc32xx_sic2_handler(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC2_BASE));
+
+	while (ints != 0) {
+		int irqno = fls(ints) - 1;
+
+		ints &= ~(1 << irqno);
+
+		handle_level_irq(SIC2_IRQ(irqno), desc);
+	}
+}
+
+void __init lpc32xx_init_irq(void)
+{
+	unsigned int i;
+
+	/* Setup MIC */
+	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
+	__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_MIC_BASE));
+	__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_MIC_BASE));
+
+	/* Setup SIC1 */
+	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
+	__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC1_BASE));
+	__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC1_BASE));
+
+	/* Setup SIC2 */
+	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
+	__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC2_BASE));
+	__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE));
+
+	/* Configure supported IRQ's */
+	for (i = 0; i < NR_IRQS; i++) {
+		set_irq_chip(i, &lpc32xx_irq_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+
+	/* Set default mappings */
+	lpc32xx_set_default_mappings(MIC_APR_DEFAULT, MIC_ATR_DEFAULT, 0);
+	lpc32xx_set_default_mappings(SIC1_APR_DEFAULT, SIC1_ATR_DEFAULT, 32);
+	lpc32xx_set_default_mappings(SIC2_APR_DEFAULT, SIC2_ATR_DEFAULT, 64);
+
+	/* MIC SUBIRQx interrupts will route handling to the chain handlers */
+	set_irq_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
+	set_irq_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
+
+	/* mask all interrupts except SUBIRQ */
+	__raw_writel((1 << IRQ_LPC32XX_SUB1IRQ) | (1 << IRQ_LPC32XX_SUB2IRQ),
+		LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
+	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
+	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
+
+	/* Initially disable all wake events */
+	__raw_writel(0, LPC32XX_CLKPWR_P01_ER);
+	__raw_writel(0, LPC32XX_CLKPWR_INT_ER);
+	__raw_writel(0, LPC32XX_CLKPWR_PIN_ER);
+
+	/*
+	 * Default wake activation polarities, all pin sources are low edge
+	 * triggered
+	 */
+	__raw_writel(LPC32XX_CLKPWR_INTSRC_TS_P_BIT |
+		LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT |
+		LPC32XX_CLKPWR_INTSRC_RTC_BIT,
+		LPC32XX_CLKPWR_INT_AP);
+	__raw_writel(0, LPC32XX_CLKPWR_PIN_AP);
+
+	/* Clear latched wake event states */
+	__raw_writel(__raw_readl(LPC32XX_CLKPWR_PIN_RS),
+		LPC32XX_CLKPWR_PIN_RS);
+	__raw_writel(__raw_readl(LPC32XX_CLKPWR_INT_RS),
+		LPC32XX_CLKPWR_INT_RS);
+}
diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c
new file mode 100644
index 0000000..630dd4a
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/timer.c
@@ -0,0 +1,182 @@
+/*
+ * arch/arm/mach-lpc32xx/timer.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * 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>
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/time.h>
+#include <linux/err.h>
+#include <linux/clockchips.h>
+
+#include <asm/mach/time.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+
+static cycle_t lpc32xx_clksrc_read(struct clocksource *cs)
+{
+	return (cycle_t)__raw_readl(LCP32XX_TIMER_TC(LPC32XX_TIMER1_BASE));
+}
+
+static struct clocksource lpc32xx_clksrc = {
+	.name	= "lpc32xx_clksrc",
+	.shift	= 24,
+	.rating	= 300,
+	.read	= lpc32xx_clksrc_read,
+	.mask	= CLOCKSOURCE_MASK(32),
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int lpc32xx_clkevt_next_event(unsigned long delta,
+    struct clock_event_device *dev)
+{
+	__raw_writel(LCP32XX_TIMER_CNTR_TCR_RESET,
+		LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
+	__raw_writel(delta, LCP32XX_TIMER_PR(LPC32XX_TIMER0_BASE));
+	__raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
+		LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
+
+	return 0;
+}
+
+static void lpc32xx_clkevt_mode(enum clock_event_mode mode,
+    struct clock_event_device *dev)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		WARN_ON(1);
+		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, LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static struct clock_event_device lpc32xx_clkevt = {
+	.name		= "lpc32xx_clkevt",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.rating		= 300,
+	.set_next_event	= lpc32xx_clkevt_next_event,
+	.set_mode	= lpc32xx_clkevt_mode,
+};
+
+static irqreturn_t lpc32xx_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &lpc32xx_clkevt;
+
+	/* Clear match */
+	__raw_writel(LCP32XX_TIMER_CNTR_MTCH_BIT(0),
+		LCP32XX_TIMER_IR(LPC32XX_TIMER0_BASE));
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction lpc32xx_timer_irq = {
+	.name		= "LPC32XX Timer Tick",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= lpc32xx_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 lpc32xx_timer_init(void)
+{
+	u32 clkrate, pllreg;
+
+	/* Enable timer clock */
+	__raw_writel(LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN |
+		LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN,
+		LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1);
+
+	/*
+	 * The clock driver isn't initialized at this point. So determine if
+	 * the SYSCLK is driven from the PLL397 or main oscillator and then use
+	 * it to compute the PLL frequency and the PCLK divider to get the base
+	 * timer rates. This rate is needed to compute the tick rate.
+	 */
+	if (clk_is_sysclk_mainosc() != 0)
+		clkrate = LPC32XX_MAIN_OSC_FREQ;
+	else
+		clkrate = 397 * LPC32XX_CLOCK_OSC_FREQ;
+
+	/* Get ARM HCLKPLL register and convert it into a frequency */
+	pllreg = __raw_readl(LPC32XX_CLKPWR_HCLKPLL_CTRL) & 0x1FFFF;
+	clkrate = clk_get_pllrate_from_reg(clkrate, pllreg);
+
+	/* Get PCLK divider and divide ARM PLL clock by it to get timer rate */
+	clkrate = clkrate / clk_get_pclk_div();
+
+	/* Initial timer setup */
+	__raw_writel(0, LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
+	__raw_writel(LCP32XX_TIMER_CNTR_MTCH_BIT(0),
+		LCP32XX_TIMER_IR(LPC32XX_TIMER0_BASE));
+	__raw_writel(1, LCP32XX_TIMER_MR0(LPC32XX_TIMER0_BASE));
+	__raw_writel(LCP32XX_TIMER_CNTR_MCR_MTCH(0) |
+		LCP32XX_TIMER_CNTR_MCR_STOP(0) |
+		LCP32XX_TIMER_CNTR_MCR_RESET(0),
+		LCP32XX_TIMER_MCR(LPC32XX_TIMER0_BASE));
+
+	/* Setup tick interrupt */
+	setup_irq(IRQ_LPC32XX_TIMER0, &lpc32xx_timer_irq);
+
+	/* Setup the clockevent structure. */
+	lpc32xx_clkevt.mult = div_sc(clkrate, NSEC_PER_SEC,
+		lpc32xx_clkevt.shift);
+	lpc32xx_clkevt.max_delta_ns = clockevent_delta2ns(-1,
+		&lpc32xx_clkevt);
+	lpc32xx_clkevt.min_delta_ns = clockevent_delta2ns(1,
+		&lpc32xx_clkevt) + 1;
+	lpc32xx_clkevt.cpumask = cpumask_of(0);
+	clockevents_register_device(&lpc32xx_clkevt);
+
+	/* Use timer1 as clock source. */
+	__raw_writel(LCP32XX_TIMER_CNTR_TCR_RESET,
+		LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
+	__raw_writel(0, LCP32XX_TIMER_PR(LPC32XX_TIMER1_BASE));
+	__raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE));
+	__raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
+		LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
+	lpc32xx_clksrc.mult = clocksource_hz2mult(clkrate,
+		lpc32xx_clksrc.shift);
+	clocksource_register(&lpc32xx_clksrc);
+}
+
+struct sys_timer lpc32xx_timer = {
+	.init		= &lpc32xx_timer_init,
+};
+
-- 
1.6.6

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

* [PATCH 05/14] ARM: LPC32XX: System suspend support
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
                   ` (3 preceding siblings ...)
  2010-02-09  0:11 ` [PATCH 04/14] ARM: LPC32XX: GPIO, timer, and IRQ drivers wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-09 17:03   ` Uwe Kleine-König
  2010-02-14 16:51   ` Pavel Machek
  2010-02-09  0:11 ` [PATCH 06/14] ARM: LPC32XX: Serial support code wellsk40 at gmail.com
                   ` (8 subsequent siblings)
  13 siblings, 2 replies; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

Support for system suspend and resume

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 arch/arm/mach-lpc32xx/pm.c      |  155 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-lpc32xx/suspend.S |  165 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 320 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-lpc32xx/pm.c b/arch/arm/mach-lpc32xx/pm.c
new file mode 100644
index 0000000..7480976
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/pm.c
@@ -0,0 +1,155 @@
+/*
+ * arch/arm/mach-lpc32xx/pm.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ * Based in part on PNX4008 power management code
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * LPC32XX CPU and system power management
+ *
+ * The LCP32XX has three CPU modes for controlling system power: run,
+ * direct-run, and halt modes. When switching between halt and run modes,
+ * the CPU transistions through direct-run mode. For Linux, direct-run
+ * mode is not used in normal operation. Halt mode is used when the
+ * system is fully suspended.
+ *
+ * Run mode:
+ * The ARM CPU clock (HCLK_PLL), HCLK bus clock, and PCLK bus clocks are
+ * derived from the HCLK PLL. The HCLK and PCLK bus rates are divided from
+ * the HCLK_PLL rate. Linux runs in this mode.
+ *
+ * Direct-run mode:
+ * The ARM CPU clock, HCLK bus clock, and PCLK bus clocks are driven from
+ * SYSCLK. SYSCLK is usually around 13MHz, but may vary based on SYSCLK
+ * source or the frequency of the main oscillator. In this mode, the
+ * HCLK_PLL can be safely enabled, changed, or disabled.
+ *
+ * Halt mode:
+ * SYSCLK is gated off and the CPU and system clocks are halted.
+ * Peripherals based on the 32KHz oscillator clock (ie, RTC, touch,
+ * key scanner, etc.) still operate if enabled. In this state, an enabled
+ * system event (ie, GPIO state change, RTC match, key press, etc.) will
+ * wake the system up back into direct-run mode.
+ *
+ * DRAM refresh
+ * DRAM clocking and refresh are slightly different for systems with DDR
+ * DRAM or regular SDRAM devices. If SDRAM is used in the system, the
+ * SDRAM will still be accessible in direct-run mode. In DDR based systems,
+ * a transistion to direct-run mode will stop all DDR accesses (no clocks).
+ * Because of this, the code to switch power modes and the code to enter
+ * and exit DRAM self-refresh modes must not be executed in DRAM. A small
+ * section of IRAM is used instead for this.
+ *
+ * Suspend is handled with the following logic:
+ *  Backup a small area of IRAM used for the suspend code
+ *  Copy suspend code to IRAM
+ *  Transfer control to code in IRAM
+ *  Places DRAMs in self-refresh mode
+ *  Enter direct-run mode
+ *  Save state of HCLK_PLL PLL
+ *  Disable HCLK_PLL PLL
+ *  Enter halt mode - CPU and buses will stop
+ *  System enters direct-run mode when an enabled event occurs
+ *  HCLK PLL state is restored
+ *  Run mode is entered
+ *  DRAMS are placed back into normal mode
+ *  Code execution returns from IRAM
+ *  IRAM code are used for suspend is restored
+ *  Suspend mode is exited
+ */
+
+#include <linux/suspend.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+#include "clock.h"
+
+#define TEMP_IRAM_AREA  IO_ADDRESS(LPC32XX_IRAM_BASE)
+
+static int lpc32xx_pm_valid_state(suspend_state_t state)
+{
+	return (state == PM_SUSPEND_MEM);
+}
+
+/*
+ * Both STANDBY and MEM suspend states are handled the same with no
+ * loss of CPU or memory state
+ */
+static int lpc32xx_pm_enter(suspend_state_t state)
+{
+	int (*lpc32xx_suspend_ptr) (void);
+	void *iram_swap_area;
+
+	/* Allocate some space for temporary IRAM storage */
+	iram_swap_area = kmalloc(lpc32xx_sys_suspend_sz, GFP_KERNEL);
+	if (!iram_swap_area) {
+		printk(KERN_ERR
+		       "PM Suspend: cannot allocate memory to save portion "
+			"of SRAM\n");
+		return -ENOMEM;
+	}
+
+	/* Backup a small area of IRAM used for the suspend code */
+	memcpy(iram_swap_area, (void *) TEMP_IRAM_AREA,
+		lpc32xx_sys_suspend_sz);
+	flush_cache_all();
+
+	/*
+	 * Copy code to suspend system into IRAM. The suspend code
+	 * needs to run from IRAM as DRAM may no longer be available
+	 * when the PLL is stopped.
+	 */
+	memcpy((void *) TEMP_IRAM_AREA, &lpc32xx_sys_suspend,
+		lpc32xx_sys_suspend_sz);
+
+	/* Transfer to suspend code in IRAM */
+	lpc32xx_suspend_ptr = (void *) TEMP_IRAM_AREA;
+	(void) lpc32xx_suspend_ptr();
+
+	/* Restore original IRAM contents */
+	memcpy((void *) TEMP_IRAM_AREA, iram_swap_area,
+		lpc32xx_sys_suspend_sz);
+
+	kfree(iram_swap_area);
+
+	return 0;
+}
+
+static struct platform_suspend_ops lpc32xx_pm_ops = {
+	.valid	= lpc32xx_pm_valid_state,
+	.enter	= lpc32xx_pm_enter,
+};
+
+#define EMC_DYN_MEM_CTRL_OFS 0x20
+#define EMC_SRMMC           (1 << 3)
+#define EMC_CTRL_REG io_p2v(LPC32XX_EMC_BASE + EMC_DYN_MEM_CTRL_OFS)
+static int __init lpc32xx_pm_init(void)
+{
+	/*
+	 * Setup SDRAM self-refresh clock to automatically
+	 * disable on start of self-refresh
+	 */
+	__raw_writel(__raw_readl(EMC_CTRL_REG) | EMC_SRMMC, EMC_CTRL_REG);
+
+	suspend_set_ops(&lpc32xx_pm_ops);
+
+	return 0;
+}
+arch_initcall(lpc32xx_pm_init);
diff --git a/arch/arm/mach-lpc32xx/suspend.S b/arch/arm/mach-lpc32xx/suspend.S
new file mode 100644
index 0000000..01c02ce
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/suspend.S
@@ -0,0 +1,165 @@
+/*
+ * arch/arm/mach-lpc32xx/suspend.S
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ * Based in part on PNX4008 power management code
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <mach/platform.h>
+#include <mach/hardware.h>
+
+/* Using named register defines makes the code easier to follow */
+#define WORK1_REG			r0
+#define WORK2_REG			r1
+#define SAVED_HCLK_DIV_REG		r2
+#define SAVED_HCLK_PLL_REG		r3
+#define SAVED_DRAM_CLKCTRL_REG		r4
+#define SAVED_PWR_CTRL_REG		r5
+#define CLKPWRBASE_REG			r6
+#define EMCBASE_REG			r7
+
+#define LPC32XX_EMC_STATUS_OFFS		0x04
+#define LPC32XX_EMC_STATUS_BUSY		0x1
+#define LPC32XX_EMC_STATUS_SELF_RFSH	0x4
+
+#define LPC32XX_CLKPWR_PWR_CTRL_OFFS	0x44
+#define LPC32XX_CLKPWR_HCLK_DIV_OFFS	0x40
+#define LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS 0x58
+
+#define CLKPWR_PCLK_DIV_MASK		0xFFFFFE7F
+
+	.text
+
+ENTRY(lpc32xx_sys_suspend)
+	@ Save a copy of the used registers in IRAM, r0 is corrupted
+	adr	r0, tmp_stack_end
+	stmfd	r0!, {r1 - r7, sp, lr}
+
+	@ Load a few common register addresses
+	adr	WORK1_REG, reg_bases
+	ldr	CLKPWRBASE_REG, [WORK1_REG, #0]
+	ldr	EMCBASE_REG, [WORK1_REG, #4]
+
+	ldr	SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+	orr	WORK1_REG, SAVED_PWR_CTRL_REG, #LPC32XX_CLKPWR_SDRAM_SELF_RFSH
+
+	@ Wait for SDRAM busy status to go busy and then idle
+	@ This guarantees a small windows where DRAM isn't busy
+1:
+	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
+	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
+	cmp	WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
+	bne	1b @ Branch while idle
+2:
+	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
+	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
+	cmp	WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
+	beq	2b @ Branch until idle
+
+	@ Setup self-refresh with support for manual exit of
+	@ self-refresh mode
+	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+	orr	WORK2_REG, WORK1_REG, #LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH
+	str	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+
+	@ Wait for self-refresh acknowledge, clocks to the DRAM device
+	@ will automatically stop on start of self-refresh
+3:
+	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
+	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH
+	cmp	WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH
+	bne	3b @ Branch until self-refresh mode starts
+
+	@ Enter direct-run mode from run mode
+	bic	WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_SELECT_RUN_MODE
+	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+
+	@ Safe disable of DRAM clock in EMC block, prevents DDR sync
+	@ issues on restart
+	ldr	SAVED_HCLK_DIV_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_HCLK_DIV_OFFS]
+	and	WORK2_REG, SAVED_HCLK_DIV_REG, #CLKPWR_PCLK_DIV_MASK
+	str	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLK_DIV_OFFS]
+
+	@ Save HCLK PLL state and disable HCLK PLL
+	ldr	SAVED_HCLK_PLL_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
+	bic	WORK2_REG, SAVED_HCLK_PLL_REG, #LPC32XX_CLKPWR_HCLKPLL_POWER_UP
+	str	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
+
+	@ Enter stop mode until an enabled event occurs
+	orr	WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_STOP_MODE_CTRL
+	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	@ Clear stop status
+	bic	WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_STOP_MODE_CTRL
+
+	@ Restore original HCLK PLL value and wait for PLL lock
+	str	SAVED_HCLK_PLL_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
+4:
+	ldr	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
+	and	WORK2_REG, WORK2_REG, #LPC32XX_CLKPWR_HCLKPLL_PLL_STS
+	bne	4b
+
+	@ Re-enter run mode with self-refresh flag cleared, but no DRAM
+	@ update yet. DRAM is still in self-refresh
+	str	SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+
+	@ Restore original DRAM clock mode to restore DRAM clocks
+	str	SAVED_HCLK_DIV_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_HCLK_DIV_OFFS]
+
+	@ Clear self-refresh mode
+	orr	WORK1_REG, SAVED_PWR_CTRL_REG,\
+		#LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH
+	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+	str	SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\
+		#LPC32XX_CLKPWR_PWR_CTRL_OFFS]
+
+	@ Wait for EMC to clear self-refresh mode
+5:
+	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
+	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH
+	bne	5b @ Branch until self-refresh has exited
+
+	@ restore regs and return
+	adr	r0, tmp_stack
+	ldmfd	r0!, {r1 - r7, sp, pc}
+
+reg_bases:
+	.long	IO_ADDRESS(LPC32XX_CLK_PM_BASE)
+	.long	IO_ADDRESS(LPC32XX_EMC_BASE)
+
+tmp_stack:
+	.long	0, 0, 0, 0, 0, 0, 0, 0, 0
+tmp_stack_end:
+
+ENTRY(lpc32xx_sys_suspend_sz)
+	.word	. - lpc32xx_sys_suspend
+
-- 
1.6.6

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

* [PATCH 06/14] ARM: LPC32XX: Serial support code
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
                   ` (4 preceding siblings ...)
  2010-02-09  0:11 ` [PATCH 05/14] ARM: LPC32XX: System suspend support wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-09  0:11 ` [PATCH 07/14] ARM: LPC32XX: Misc support functions wellsk40 at gmail.com
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

Serial port setup support code

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 arch/arm/mach-lpc32xx/serial.c |  191 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 191 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-lpc32xx/serial.c b/arch/arm/mach-lpc32xx/serial.c
new file mode 100644
index 0000000..680a79b
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/serial.c
@@ -0,0 +1,191 @@
+/*
+ * arch/arm/mach-lpc32xx/serial.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/serial_8250.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <mach/io.h>
+#include "common.h"
+
+#define LPC32XX_SUART_FIFO_SIZE	64
+
+/* Standard 8250/16550 compatible serial ports */
+static struct plat_serial8250_port serial_std_platform_data[] = {
+#ifdef CONFIG_ARCH_LPC32XX_UART5_SELECT
+	{
+		.membase        = io_p2v(LPC32XX_UART5_BASE),
+		.mapbase        = LPC32XX_UART5_BASE,
+		.irq		= IRQ_LPC32XX_UART_IIR5,
+		.uartclk	= LPC32XX_MAIN_OSC_FREQ,
+		.regshift	= 2,
+		.iotype		= UPIO_MEM32,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
+					UPF_SKIP_TEST,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART3_SELECT
+	{
+		.membase	= io_p2v(LPC32XX_UART3_BASE),
+		.mapbase        = LPC32XX_UART3_BASE,
+		.irq		= IRQ_LPC32XX_UART_IIR3,
+		.uartclk	= LPC32XX_MAIN_OSC_FREQ,
+		.regshift	= 2,
+		.iotype		= UPIO_MEM32,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
+					UPF_SKIP_TEST,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART4_SELECT
+	{
+		.membase	= io_p2v(LPC32XX_UART4_BASE),
+		.mapbase        = LPC32XX_UART4_BASE,
+		.irq		= IRQ_LPC32XX_UART_IIR4,
+		.uartclk	= LPC32XX_MAIN_OSC_FREQ,
+		.regshift	= 2,
+		.iotype		= UPIO_MEM32,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
+					UPF_SKIP_TEST,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART6_SELECT
+	{
+		.membase	= io_p2v(LPC32XX_UART6_BASE),
+		.mapbase        = LPC32XX_UART6_BASE,
+		.irq		= IRQ_LPC32XX_UART_IIR6,
+		.uartclk	= LPC32XX_MAIN_OSC_FREQ,
+		.regshift	= 2,
+		.iotype		= UPIO_MEM32,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
+					UPF_SKIP_TEST,
+	},
+#endif
+	{ },
+};
+
+struct uartinit {
+	char *uart_ck_name;
+	u32 ck_mode_mask;
+	void __iomem *pdiv_clk_reg;
+};
+
+static struct uartinit uartinit_data[] __initdata = {
+#ifdef CONFIG_ARCH_LPC32XX_UART5_SELECT
+	{
+		.uart_ck_name = "uart5_ck",
+		.ck_mode_mask =
+			LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 5),
+		.pdiv_clk_reg = LPC32XX_CLKPWR_UART5_CLK_CTRL,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART3_SELECT
+	{
+		.uart_ck_name = "uart3_ck",
+		.ck_mode_mask =
+			LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 3),
+		.pdiv_clk_reg = LPC32XX_CLKPWR_UART3_CLK_CTRL,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART4_SELECT
+	{
+		.uart_ck_name = "uart4_ck",
+		.ck_mode_mask =
+			LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 4),
+		.pdiv_clk_reg = LPC32XX_CLKPWR_UART4_CLK_CTRL,
+	},
+#endif
+#ifdef CONFIG_ARCH_LPC32XX_UART6_SELECT
+	{
+		.uart_ck_name = "uart6_ck",
+		.ck_mode_mask =
+			LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 6),
+		.pdiv_clk_reg = LPC32XX_CLKPWR_UART6_CLK_CTRL,
+	},
+#endif
+};
+
+static struct platform_device serial_std_platform_device = {
+	.name			= "serial8250",
+	.id			= 0,
+	.dev			= {
+		.platform_data	= serial_std_platform_data,
+	},
+};
+
+static struct platform_device *lpc32xx_serial_devs[] __initdata = {
+	&serial_std_platform_device,
+};
+
+void __init lpc32xx_serial_init(void)
+{
+	u32 tmp, clkmodes = 0;
+	struct clk *clk;
+	unsigned int puart;
+	int i, j;
+
+	/* UART clocks are off, let clock driver manage them */
+	__raw_writel(0, LPC32XX_CLKPWR_UART_CLK_CTRL);
+
+	for (i = 0; i < ARRAY_SIZE(uartinit_data); i++) {
+		clk = clk_get(NULL, uartinit_data[i].uart_ck_name);
+		if (!IS_ERR(clk)) {
+			clk_enable(clk);
+			serial_std_platform_data[i].uartclk =
+				clk_get_rate(clk);
+		}
+
+		/* Fall back on main osc rate if clock rate return fails */
+		if (serial_std_platform_data[i].uartclk == 0)
+			serial_std_platform_data[i].uartclk =
+				LPC32XX_MAIN_OSC_FREQ;
+
+		/* Setup UART clock modes for all UARTs, disable autoclock */
+		clkmodes |= uartinit_data[i].ck_mode_mask;
+
+		/* pre-UART clock divider set to 1 */
+		__raw_writel(0x0101, uartinit_data[i].pdiv_clk_reg);
+	}
+
+	/* This needs to be done after all UART clocks are setup */
+	__raw_writel(clkmodes, LPC32XX_UARTCTL_CLKMODE);
+	for (i = 0; i < ARRAY_SIZE(uartinit_data) - 1; i++) {
+		/* Force a flush of the RX FIFOs to work around a HW bug */
+		puart = serial_std_platform_data[i].mapbase;
+		__raw_writel(0xC1, LPC32XX_UART_IIR_FCR(puart));
+		__raw_writel(0x00, LPC32XX_UART_DLL_FIFO(puart));
+		j = LPC32XX_SUART_FIFO_SIZE;
+		while (j--)
+			tmp = __raw_readl(LPC32XX_UART_DLL_FIFO(puart));
+		__raw_writel(0, LPC32XX_UART_IIR_FCR(puart));
+	}
+
+	/* Disable UART5->USB transparent mode or USB won't work */
+	tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
+	tmp &= ~LPC32XX_UART_U5_ROUTE_TO_USB;
+	__raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
+
+	platform_add_devices(lpc32xx_serial_devs,
+		ARRAY_SIZE(lpc32xx_serial_devs));
+}
-- 
1.6.6

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

* [PATCH 07/14] ARM: LPC32XX: Misc support functions
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
                   ` (5 preceding siblings ...)
  2010-02-09  0:11 ` [PATCH 06/14] ARM: LPC32XX: Serial support code wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-12 20:06   ` Uwe Kleine-König
  2010-02-09  0:11 ` [PATCH 08/14] ARM: LPC32XX: Phytec 3250 platform support wellsk40 at gmail.com
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

Misc support functions and prototypes used in the LPC32XX arch
and platforms

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 arch/arm/mach-lpc32xx/common.c |  296 ++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-lpc32xx/common.h |   75 ++++++++++
 2 files changed, 371 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-lpc32xx/common.c b/arch/arm/mach-lpc32xx/common.c
new file mode 100644
index 0000000..e0ce595
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/common.c
@@ -0,0 +1,296 @@
+/*
+ * arch/arm/mach-lpc32xx/common.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/i2c-pnx.h>
+#include <linux/io.h>
+
+#include <asm/mach/map.h>
+
+#include <mach/i2c.h>
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include "common.h"
+
+/*
+ * Watchdog timer
+ */
+static struct resource watchdog_resources[] = {
+	[0] = {
+		.start = LPC32XX_WDTIM_BASE,
+		.end = LPC32XX_WDTIM_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device watchdog_device = {
+	.name = "pnx4008-watchdog",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(watchdog_resources),
+	.resource = watchdog_resources,
+};
+
+/*
+ * I2C busses
+ */
+static struct i2c_pnx_data i2c0_data = {
+	.name = I2C_CHIP_NAME "1",
+	.base = LPC32XX_I2C1_BASE,
+	.irq = IRQ_LPC32XX_I2C_1,
+};
+
+static struct i2c_pnx_data i2c1_data = {
+	.name = I2C_CHIP_NAME "2",
+	.base = LPC32XX_I2C2_BASE,
+	.irq = IRQ_LPC32XX_I2C_2,
+};
+
+static struct i2c_pnx_data i2c2_data = {
+	.name = "USB-I2C",
+	.base = LPC32XX_OTG_I2C_BASE,
+	.irq = IRQ_LPC32XX_USB_I2C,
+};
+
+struct platform_device i2c0_device = {
+	.name = "pnx-i2c",
+	.id = 0,
+	.dev = {
+		.platform_data = &i2c0_data,
+	},
+};
+
+struct platform_device i2c1_device = {
+	.name = "pnx-i2c",
+	.id = 1,
+	.dev = {
+		.platform_data = &i2c1_data,
+	},
+};
+
+struct platform_device i2c2_device = {
+	.name = "pnx-i2c",
+	.id = 2,
+	.dev = {
+		.platform_data = &i2c2_data,
+	},
+};
+
+/*
+ * Returns the unique ID for the device
+ */
+void lpc32xx_get_uid(u32 devid[4])
+{
+	int i;
+
+	for (i = 0; i < 4; i++)
+		devid[i] = __raw_readl(LPC32XX_CLKPWR_DEVID(i << 2));
+}
+
+/*
+ * Returns SYSCLK source
+ * 0 = PLL397, 1 = main oscillator
+ */
+int clk_is_sysclk_mainosc(void)
+{
+	if ((__raw_readl(LPC32XX_CLKPWR_SYSCLK_CTRL) &
+		LPC32XX_CLKPWR_SYSCTRL_SYSCLKMUX) == 0)
+		return 1;
+
+	return 0;
+}
+
+/*
+ * System reset via the watchdog timer
+ */
+void lpc32xx_watchdog_reset(void)
+{
+	/* Make sure WDT clocks are enabled */
+	__raw_writel(LPC32XX_CLKPWR_PWMCLK_WDOG_EN,
+		LPC32XX_CLKPWR_TIMER_CLK_CTRL);
+
+	/* Instant assert of RESETOUT_N with pulse length 1mS */
+	__raw_writel(13000, io_p2v(LPC32XX_WDTIM_BASE + 0x18));
+	__raw_writel(0x70, io_p2v(LPC32XX_WDTIM_BASE + 0xC));
+}
+
+/*
+ * Detects and returns IRAM size for the device variation
+ */
+#define LPC32XX_IRAM_BANK_SIZE (128 * SZ_1K)
+static u32 iram_size;
+u32 lpc32xx_return_iram_size(void)
+{
+	if (iram_size == 0) {
+		u32 savedval;
+		void __iomem *iramptr1, *iramptr2;
+
+		iramptr1 = io_p2v(LPC32XX_IRAM_BASE);
+		iramptr2 = io_p2v(LPC32XX_IRAM_BASE + LPC32XX_IRAM_BANK_SIZE);
+		savedval = __raw_readl(iramptr2);
+
+		__raw_writel(savedval + 1, iramptr2);
+
+		/*
+		 * If IRAM size is 128K, the value@iramptr2 will wrap back
+		 * into iramptr1
+		 */
+		if (__raw_readl(iramptr1) == __raw_readl(iramptr2))
+			iram_size = LPC32XX_IRAM_BANK_SIZE;
+		else
+			iram_size = LPC32XX_IRAM_BANK_SIZE * 2;
+
+		__raw_writel(savedval, iramptr2);
+	}
+
+	return iram_size;
+}
+
+/*
+ * Computes PLL rate from PLL register and input clock
+ */
+u32 clk_check_pll_setup(u32 ifreq, struct clk_pll_setup *pllsetup)
+{
+	u32 ilfreq, p, m, n, fcco, fref, cfreq;
+	int mode;
+
+	/*
+	 * PLL requirements
+	 * ifreq must be >= 1MHz and <= 20MHz
+	 * FCCO must be >= 156MHz and <= 320MHz
+	 * FREF must be >= 1MHz and <= 27MHz
+	 * Assume the passed input data is not valid
+	 */
+
+	ilfreq = ifreq;
+	m = pllsetup->pll_m;
+	n = pllsetup->pll_n;
+	p = pllsetup->pll_p;
+
+	mode = (pllsetup->cco_bypass_b15 << 2) |
+		(pllsetup->direct_output_b14 << 1) |
+	pllsetup->fdbk_div_ctrl_b13;
+
+	switch (mode) {
+	case 0x0: /* Non-integer mode */
+		cfreq = (m * ilfreq) / (2 * p * n);
+		fcco = (m * ilfreq) / n;
+		fref = ilfreq / n;
+		break;
+
+	case 0x1: /* integer mode */
+		cfreq = (m * ilfreq) / n;
+		fcco = (m * ilfreq) / (n * 2 * p);
+		fref = ilfreq / n;
+		break;
+
+	case 0x2:
+	case 0x3: /* Direct mode */
+		cfreq = (m * ilfreq) / n;
+		fcco = cfreq;
+		fref = ilfreq / n;
+		break;
+
+	case 0x4:
+	case 0x5: /* Bypass mode */
+		cfreq = ilfreq / (2 * p);
+		fcco = 156000000;
+		fref = 1000000;
+		break;
+
+	case 0x6:
+	case 0x7: /* Direct bypass mode */
+	default:
+		cfreq = ilfreq;
+		fcco = 156000000;
+		fref = 1000000;
+		break;
+	}
+
+	if (fcco < 156000000 || fcco > 320000000)
+		cfreq = 0;
+
+	if (fref < 1000000 || fref > 27000000)
+		cfreq = 0;
+
+	return (u32) cfreq;
+}
+
+/*
+ * Convert a PLL register value to a PLL output frequency
+ */
+u32 clk_get_pllrate_from_reg(u32 inputclk, u32 regval)
+{
+	struct clk_pll_setup pllcfg;
+
+	pllcfg.cco_bypass_b15 = 0;
+	pllcfg.direct_output_b14 = 0;
+	pllcfg.fdbk_div_ctrl_b13 = 0;
+	if ((regval & LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS) != 0)
+		pllcfg.cco_bypass_b15 = 1;
+	if ((regval & LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS) != 0)
+		pllcfg.direct_output_b14 = 1;
+	if ((regval & LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK) != 0)
+		pllcfg.fdbk_div_ctrl_b13 = 1;
+	pllcfg.pll_m = 1 + ((regval >> 1) & 0xFF);
+	pllcfg.pll_n = 1 + ((regval >> 9) & 0x3);
+	pllcfg.pll_p = pll_postdivs[((regval >> 11) & 0x3)];
+
+	return clk_check_pll_setup(inputclk, &pllcfg);
+}
+
+u32 clk_get_pclk_div(void)
+{
+	return 1 + ((__raw_readl(LPC32XX_CLKPWR_HCLK_DIV) >> 2) & 0x1F);
+}
+
+static struct map_desc lpc32xx_io_desc[] __initdata = {
+	{
+		.virtual	= IO_ADDRESS(LPC32XX_AHB0_START),
+		.pfn		= __phys_to_pfn(LPC32XX_AHB0_START),
+		.length		= LPC32XX_AHB0_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= IO_ADDRESS(LPC32XX_AHB1_START),
+		.pfn		= __phys_to_pfn(LPC32XX_AHB1_START),
+		.length		= LPC32XX_AHB1_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= IO_ADDRESS(LPC32XX_FABAPB_START),
+		.pfn		= __phys_to_pfn(LPC32XX_FABAPB_START),
+		.length		= LPC32XX_FABAPB_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= IO_ADDRESS(LPC32XX_IRAM_BASE),
+		.pfn		= __phys_to_pfn(LPC32XX_IRAM_BASE),
+		.length		= (256 * SZ_1K),
+		.type		= MT_DEVICE
+	},
+};
+
+void __init lpc32xx_map_io(void)
+{
+	iotable_init(lpc32xx_io_desc, ARRAY_SIZE(lpc32xx_io_desc));
+}
diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h
new file mode 100644
index 0000000..8161efe
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/common.h
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/mach-lpc32xx/common.h
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2009-2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LPC32XX_COMMON_H
+#define __LPC32XX_COMMON_H
+
+#include <linux/platform_device.h>
+
+/*
+ * Arch specific platform device structures
+ */
+extern struct platform_device watchdog_device;
+extern struct platform_device i2c0_device;
+extern struct platform_device i2c1_device;
+extern struct platform_device i2c2_device;
+
+/*
+ * Other arch specific structures and functions
+ */
+extern struct sys_timer lpc32xx_timer;
+extern void __init lpc32xx_init_irq(void);
+extern void __init lpc32xx_map_io(void);
+extern void __init lpc32xx_serial_init(void);
+extern void __init lpc32xx_gpio_init(void);
+
+/*
+ * Structure used for setting up and querying the PLLS
+ */
+struct clk_pll_setup {
+	int analog_on;
+	int cco_bypass_b15;
+	int direct_output_b14;
+	int fdbk_div_ctrl_b13;
+	int pll_p;
+	int pll_n;
+	u32 pll_m;
+};
+
+extern const u32 pll_postdivs[4];
+
+extern int clk_is_sysclk_mainosc(void);
+extern u32 clk_check_pll_setup(u32 ifreq, struct clk_pll_setup *pllsetup);
+extern u32 clk_get_pllrate_from_reg(u32 inputclk, u32 regval);
+extern u32 clk_get_pclk_div(void);
+
+/*
+ * Returns the LPC32xx unique 128-bit chip ID
+ */
+extern void lpc32xx_get_uid(u32 devid[4]);
+
+extern void lpc32xx_watchdog_reset(void);
+extern u32 lpc32xx_return_iram_size(void);
+
+/*
+ * Pointers used for sizing and copying suspend function data
+ */
+extern int lpc32xx_sys_suspend(void);
+extern int lpc32xx_sys_suspend_sz;
+
+#endif
-- 
1.6.6

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

* [PATCH 08/14] ARM: LPC32XX: Phytec 3250 platform support
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
                   ` (6 preceding siblings ...)
  2010-02-09  0:11 ` [PATCH 07/14] ARM: LPC32XX: Misc support functions wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-12 20:08   ` Uwe Kleine-König
  2010-02-09  0:11 ` [PATCH 09/14] ARM: LPC32XX: Arch config menu supoport and makefiles wellsk40 at gmail.com
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

Platform support file for the PHY3250 mach id

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 arch/arm/mach-lpc32xx/phy3250.c |  385 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 385 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
new file mode 100644
index 0000000..62bdb62
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/phy3250.c
@@ -0,0 +1,385 @@
+/*
+ * arch/arm/mach-lpc32xx/phy3250.c
+ *
+ * Author: Kevin Wells <kevin.wells@nxp.com>
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/sysdev.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/eeprom.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <linux/amba/pl022.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/hardware.h>
+#include <mach/platform.h>
+#include <mach/board.h>
+#include "common.h"
+
+/*
+ * Mapped GPIOLIB GPIOs
+ */
+#define SPI0_CS_GPIO	LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
+#define LCD_POWER_GPIO	LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0)
+#define BKL_POWER_GPIO	LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4)
+#define LED_GPIO	LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 1)
+
+/*
+ * AMBA LCD controller
+ */
+static struct clcd_panel conn_lcd_panel = {
+	.mode		= {
+		.name		= "QVGA portrait",
+		.refresh	= 60,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 191828,
+		.left_margin	= 22,
+		.right_margin	= 11,
+		.upper_margin	= 2,
+		.lower_margin	= 1,
+		.hsync_len	= 5,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= (TIM2_IVS | TIM2_IHS),
+	.cntl		= (CNTL_BGR | CNTL_LCDTFT | CNTL_LCDVCOMP(1) |
+				CNTL_LCDBPP16_565),
+	.bpp		= 16,
+};
+#define PANEL_SIZE (3 * SZ_64K)
+
+static int lpc32xx_clcd_setup(struct clcd_fb *fb)
+{
+	dma_addr_t dma;
+
+	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev,
+		PANEL_SIZE, &dma, GFP_KERNEL);
+	if (!fb->fb.screen_base) {
+		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+	fb->fb.fix.smem_start = dma;
+	fb->fb.fix.smem_len = PANEL_SIZE;
+	fb->panel = &conn_lcd_panel;
+
+	gpio_request(LCD_POWER_GPIO, "LCD power");
+	gpio_direction_output(LCD_POWER_GPIO, 1);
+	gpio_request(BKL_POWER_GPIO, "LCD backlight power");
+	gpio_direction_output(BKL_POWER_GPIO, 1);
+
+	return 0;
+}
+
+static int lpc32xx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	return dma_mmap_writecombine(&fb->dev->dev, vma,
+		fb->fb.screen_base, fb->fb.fix.smem_start,
+		fb->fb.fix.smem_len);
+}
+
+static void lpc32xx_clcd_remove(struct clcd_fb *fb)
+{
+	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+		fb->fb.screen_base, fb->fb.fix.smem_start);
+}
+
+/*
+ * On some early LCD modules (1307.0), the backlight logic is inverted.
+ * For those board variants, swap the disable and enable states for
+ * BKL_POWER_GPIO.
+*/
+static void clcd_disable(struct clcd_fb *fb)
+{
+	gpio_set_value(BKL_POWER_GPIO, 0);
+	gpio_set_value(LCD_POWER_GPIO, 0);
+}
+
+static void clcd_enable(struct clcd_fb *fb)
+{
+	gpio_set_value(BKL_POWER_GPIO, 1);
+	gpio_set_value(LCD_POWER_GPIO, 1);
+}
+
+static struct clcd_board lpc32xx_clcd_data = {
+	.name		= "Phytec LCD",
+	.check		= clcdfb_check,
+	.decode		= clcdfb_decode,
+	.disable	= clcd_disable,
+	.enable		= clcd_enable,
+	.setup		= lpc32xx_clcd_setup,
+	.mmap		= lpc32xx_clcd_mmap,
+	.remove		= lpc32xx_clcd_remove,
+};
+
+static struct amba_device clcd_device = {
+	.dev				= {
+		.coherent_dma_mask	= ~0,
+		.init_name		= "dev:clcd",
+		.platform_data		= &lpc32xx_clcd_data,
+	},
+	.res				= {
+		.start			= LPC32XX_LCD_BASE,
+		.end			= (LPC32XX_LCD_BASE + SZ_4K - 1),
+		.flags			= IORESOURCE_MEM,
+	},
+	.dma_mask			= ~0,
+	.irq				= {IRQ_LPC32XX_LCD, NO_IRQ},
+};
+
+/*
+ * AMBA SSP (SPI)
+ */
+static void phy3250_spi_cs_set(u32 control)
+{
+	gpio_set_value(SPI0_CS_GPIO, (int) control);
+}
+
+static struct pl022_config_chip spi0_chip_info = {
+	.lbm			= LOOPBACK_DISABLED,
+	.com_mode		= INTERRUPT_TRANSFER,
+	.iface			= SSP_INTERFACE_MOTOROLA_SPI,
+	.hierarchy		= SSP_MASTER,
+	.slave_tx_disable	= 0,
+	.endian_tx		= SSP_TX_LSB,
+	.endian_rx		= SSP_RX_LSB,
+	.data_size		= SSP_DATA_BITS_8,
+	.rx_lev_trig		= SSP_RX_4_OR_MORE_ELEM,
+	.tx_lev_trig		= SSP_TX_4_OR_MORE_EMPTY_LOC,
+	.clk_phase		= SSP_CLK_FIRST_EDGE,
+	.clk_pol		= SSP_CLK_POL_IDLE_LOW,
+	.ctrl_len		= SSP_BITS_8,
+	.wait_state		= SSP_MWIRE_WAIT_ZERO,
+	.duplex			= SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
+	.cs_control		= phy3250_spi_cs_set,
+};
+
+static struct pl022_ssp_controller lpc32xx_ssp0_data = {
+	.bus_id			= 0,
+	.num_chipselect		= 1,
+	.enable_dma		= 0,
+};
+
+static struct amba_device ssp0_device = {
+	.dev				= {
+		.coherent_dma_mask	= ~0,
+		.init_name		= "dev:ssp0",
+		.platform_data		= &lpc32xx_ssp0_data,
+	},
+	.res				= {
+		.start			= LPC32XX_SSP0_BASE,
+		.end			= (LPC32XX_SSP0_BASE + SZ_4K - 1),
+		.flags			= IORESOURCE_MEM,
+	},
+	.dma_mask			= ~0,
+	.irq				= {IRQ_LPC32XX_SSP0, NO_IRQ},
+};
+
+/* AT25 driver registration */
+static int __init phy3250_spi_board_register(void)
+{
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+	static struct spi_board_info info[] = {
+		{
+			.modalias = "spidev",
+			.max_speed_hz = 5000000,
+			.bus_num = 0,
+			.chip_select = 0,
+			.controller_data = &spi0_chip_info,
+		},
+	};
+
+#else
+	static struct spi_eeprom eeprom = {
+		.name = "at25256a",
+		.byte_len = 0x8000,
+		.page_size = 64,
+		.flags = EE_ADDR2,
+	};
+
+	static struct spi_board_info info[] = {
+		{
+			.modalias = "at25",
+			.max_speed_hz = 5000000,
+			.bus_num = 0,
+			.chip_select = 0,
+			.platform_data = &eeprom,
+			.controller_data = &spi0_chip_info,
+		},
+	};
+#endif
+	return spi_register_board_info(info, ARRAY_SIZE(info));
+}
+arch_initcall(phy3250_spi_board_register);
+
+static struct i2c_board_info __initdata phy3250_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO("pcf8563", 0x51),
+	},
+};
+
+static struct gpio_led phy_leds[] = {
+	{
+		.name			= "led0",
+		.gpio			= LED_GPIO,
+		.active_low		= 1,
+		.default_trigger	= "heartbeat",
+	},
+};
+
+static struct gpio_led_platform_data led_data = {
+	.leds = phy_leds,
+	.num_leds = ARRAY_SIZE(phy_leds),
+};
+
+static struct platform_device lpc32xx_gpio_led_device = {
+	.name			= "leds-gpio",
+	.id			= -1,
+	.dev.platform_data	= &led_data,
+};
+
+static struct platform_device *phy3250_devs[] __initdata = {
+	&i2c0_device,
+	&i2c1_device,
+	&i2c2_device,
+	&watchdog_device,
+	&lpc32xx_gpio_led_device,
+};
+
+static struct amba_device *amba_devs[] __initdata = {
+	&clcd_device,
+	&ssp0_device,
+};
+
+/*
+ * Board specific functions
+ */
+static void __init phy3250_board_init(void)
+{
+	u32 tmp;
+	int i;
+
+	lpc32xx_gpio_init();
+
+	/* Register GPIOs used on this board */
+	gpio_request(SPI0_CS_GPIO, "spi0 cs");
+	gpio_direction_output(SPI0_CS_GPIO, 1);
+
+	/* Setup network interface for RMII mode */
+	tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL);
+	tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK;
+	tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS;
+	__raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL);
+
+	/* Setup SLC NAND controller muxing */
+	__raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
+		LPC32XX_CLKPWR_NAND_CLK_CTRL);
+
+	/* Setup LCD muxing to RGB565 */
+	tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) &
+		~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK |
+		LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK);
+	tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16;
+	__raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL);
+
+	/* Set up I2C pull levels */
+	tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
+	tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE |
+		LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE;
+	__raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
+
+	/* Disable IrDA pulsing support on UART6 */
+	tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
+	tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS;
+	__raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
+
+	/* Enable DMA for I2S1 channel */
+	tmp = __raw_readl(LPC32XX_CLKPWR_I2S_CLK_CTRL);
+	tmp = LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA;
+	__raw_writel(tmp, LPC32XX_CLKPWR_I2S_CLK_CTRL);
+
+	lpc32xx_serial_init();
+
+	/*
+	 * AMBA peripheral clocks need to be enabled prior to AMBA device
+	 * detection or a data fault will occur, so enable the clocks
+	 * here. However, we don't want to enable them if the peripheral
+	 * isn't included in the image
+	 */
+#ifdef CONFIG_FB_ARMCLCD
+	tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
+	__raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN),
+		LPC32XX_CLKPWR_LCDCLK_CTRL);
+#endif
+#ifdef CONFIG_SPI_PL022
+	tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL);
+	__raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN),
+		LPC32XX_CLKPWR_SSP_CLK_CTRL);
+#endif
+
+	platform_add_devices(phy3250_devs, ARRAY_SIZE(phy3250_devs));
+	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+		struct amba_device *d = amba_devs[i];
+		amba_device_register(d, &iomem_resource);
+	}
+
+	/* Test clock needed for UDA1380 initial init */
+	__raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC |
+		LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
+		LPC32XX_CLKPWR_TEST_CLK_SEL);
+
+	i2c_register_board_info(0, phy3250_i2c_board_info,
+		ARRAY_SIZE(phy3250_i2c_board_info));
+}
+
+static int __init lpc32xx_display_uid(void)
+{
+	u32 uid[4];
+
+	lpc32xx_get_uid(uid);
+
+	printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n",
+		uid[3], uid[2], uid[1], uid[0]);
+
+	return 1;
+}
+arch_initcall(lpc32xx_display_uid);
+
+MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
+	/* Maintainer: Kevin Wells, NXP Semiconductors */
+	.phys_io	= LPC32XX_UART5_BASE,
+	.io_pg_offst	= ((IO_ADDRESS(LPC32XX_UART5_BASE))>>18) & 0xfffc,
+	.boot_params	= 0x80000100,
+	.map_io		= lpc32xx_map_io,
+	.init_irq	= lpc32xx_init_irq,
+	.timer		= &lpc32xx_timer,
+	.init_machine	= phy3250_board_init,
+MACHINE_END
-- 
1.6.6

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

* [PATCH 09/14] ARM: LPC32XX: Arch config menu supoport and makefiles
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
                   ` (7 preceding siblings ...)
  2010-02-09  0:11 ` [PATCH 08/14] ARM: LPC32XX: Phytec 3250 platform support wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-09  0:11 ` [PATCH 10/14] ARM: LPC32XX: Default PHY3250 kernel config (ramdisk) wellsk40 at gmail.com
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>


Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 arch/arm/mach-lpc32xx/Kconfig       |   33 +++++++++++++++++++++++++++++++++
 arch/arm/mach-lpc32xx/Makefile      |    8 ++++++++
 arch/arm/mach-lpc32xx/Makefile.boot |    4 ++++
 3 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-lpc32xx/Kconfig b/arch/arm/mach-lpc32xx/Kconfig
new file mode 100644
index 0000000..fde6635
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/Kconfig
@@ -0,0 +1,33 @@
+if ARCH_LPC32XX
+
+menu "Individual UART enable selections"
+
+config ARCH_LPC32XX_UART3_SELECT
+	bool "Add support for standard UART3"
+	help
+	 Adds support for standard UART 3 when the 8250 serial support
+	 is enabled.
+
+config ARCH_LPC32XX_UART4_SELECT
+	bool "Add support for standard UART4"
+	help
+	 Adds support for standard UART 4 when the 8250 serial support
+	 is enabled.
+
+config ARCH_LPC32XX_UART5_SELECT
+	bool "Add support for standard UART5"
+	default y
+	help
+	 Adds support for standard UART 5 when the 8250 serial support
+	 is enabled.
+
+config ARCH_LPC32XX_UART6_SELECT
+	bool "Add support for standard UART6"
+	help
+	 Adds support for standard UART 6 when the 8250 serial support
+	 is enabled.
+
+endmenu
+
+endif
+
diff --git a/arch/arm/mach-lpc32xx/Makefile b/arch/arm/mach-lpc32xx/Makefile
new file mode 100644
index 0000000..a5fc5d0
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y	:= timer.o irq.o common.o serial.o clock.o
+obj-y	+= gpiolib.o pm.o suspend.o
+obj-y	+= phy3250.o
+
diff --git a/arch/arm/mach-lpc32xx/Makefile.boot b/arch/arm/mach-lpc32xx/Makefile.boot
new file mode 100644
index 0000000..b796b41
--- /dev/null
+++ b/arch/arm/mach-lpc32xx/Makefile.boot
@@ -0,0 +1,4 @@
+   zreladdr-y	:= 0x80008000
+params_phys-y	:= 0x80000100
+initrd_phys-y	:= 0x82000000
+
-- 
1.6.6

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

* [PATCH 10/14] ARM: LPC32XX: Default PHY3250 kernel config (ramdisk)
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
                   ` (8 preceding siblings ...)
  2010-02-09  0:11 ` [PATCH 09/14] ARM: LPC32XX: Arch config menu supoport and makefiles wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-09  0:11 ` [PATCH 11/14] ARM: Add support for the LPC32XX arch wellsk40 at gmail.com
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>


Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 arch/arm/configs/phy3250_defconfig | 1084 ++++++++++++++++++++++++++++++++++++
 1 files changed, 1084 insertions(+), 0 deletions(-)

diff --git a/arch/arm/configs/phy3250_defconfig b/arch/arm/configs/phy3250_defconfig
new file mode 100644
index 0000000..2c0145c
--- /dev/null
+++ b/arch/arm/configs/phy3250_defconfig
@@ -0,0 +1,1084 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.33-rc6
+# Mon Feb  8 13:45:54 2010
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TREE_RCU=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+# CONFIG_TINY_RCU is not set
+# CONFIG_RCU_TRACE is not set
+CONFIG_RCU_FANOUT=32
+# CONFIG_RCU_FANOUT_EXACT is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_LZO is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+CONFIG_ARCH_LPC32XX=y
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_U8500 is not set
+
+#
+# Individual UART enable selections
+#
+# CONFIG_ARCH_LPC32XX_UART3_SELECT is not set
+# CONFIG_ARCH_LPC32XX_UART4_SELECT is not set
+CONFIG_ARCH_LPC32XX_UART5_SELECT=y
+# CONFIG_ARCH_LPC32XX_UART6_SELECT is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+CONFIG_ARM_AMBA=y
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=tty0 console=ttyS0,115200n81 root=/dev/ram0 init=/sbin/init"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+CONFIG_BINFMT_AOUT=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_APM_EMULATION is not set
+# CONFIG_PM_RUNTIME is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_CRYPTOLOOP=y
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_MG_DISK is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+CONFIG_EEPROM_AT25=y
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+CONFIG_I2C_PNX=y
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_PL022=y
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_PL061 is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+
+#
+# AC97 GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_PNX4008_WATCHDOG=y
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13783 is not set
+# CONFIG_AB3100_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_88PM8607 is not set
+# CONFIG_AB4500_CORE is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_ARMCLCD=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_ARCH_HAS_OHCI=y
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+
+#
+# TI VLYNQ
+#
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_FILE_LOCKING is not set
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY is not set
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=y
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
-- 
1.6.6

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

* [PATCH 11/14] ARM: Add support for the LPC32XX arch
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
                   ` (9 preceding siblings ...)
  2010-02-09  0:11 ` [PATCH 10/14] ARM: LPC32XX: Default PHY3250 kernel config (ramdisk) wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-09  0:11 ` [PATCH 12/14] AMBA: CLCD: LPC32XX register swap in the clcd header file wellsk40 at gmail.com
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

Add LPC32XX support in arch/arm/Kconfig and arch/arm/Makefile

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 arch/arm/Kconfig  |   15 +++++++++++++++
 arch/arm/Makefile |    1 +
 2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 184a6bd..872f888 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -550,6 +550,19 @@ config ARCH_W90X900
 	  <http://www.nuvoton.com/hq/enu/ProductAndSales/ProductLines/
 		ConsumerElectronicsIC/ARMMicrocontroller/ARMMicrocontroller>
 
+config ARCH_LPC32XX
+	bool "NXP LPC32XX"
+	select CPU_ARM926T
+	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_IDE
+	select ARM_AMBA
+	select USB_ARCH_HAS_OHCI
+	select COMMON_CLKDEV
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	help
+	  Support for the NXP LPC32XX family of processors
+
 config ARCH_PNX4008
 	bool "Philips Nexperia PNX4008 Mobile"
 	select CPU_ARM926T
@@ -772,6 +785,8 @@ source "arch/arm/mach-lh7a40x/Kconfig"
 
 source "arch/arm/mach-loki/Kconfig"
 
+source "arch/arm/mach-lpc32xx/Kconfig"
+
 source "arch/arm/mach-msm/Kconfig"
 
 source "arch/arm/mach-mv78xx0/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 356d702..36f39db 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -139,6 +139,7 @@ machine-$(CONFIG_ARCH_KS8695)		:= ks8695
 machine-$(CONFIG_ARCH_L7200)		:= l7200
 machine-$(CONFIG_ARCH_LH7A40X)		:= lh7a40x
 machine-$(CONFIG_ARCH_LOKI) 		:= loki
+machine-$(CONFIG_ARCH_LPC32XX) 		:= lpc32xx
 machine-$(CONFIG_ARCH_MMP)		:= mmp
 machine-$(CONFIG_ARCH_MSM)		:= msm
 machine-$(CONFIG_ARCH_MV78XX0)		:= mv78xx0
-- 
1.6.6

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

* [PATCH 12/14] AMBA: CLCD: LPC32XX register swap in the clcd header file
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
                   ` (10 preceding siblings ...)
  2010-02-09  0:11 ` [PATCH 11/14] ARM: Add support for the LPC32XX arch wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-12 14:31   ` Russell King - ARM Linux
  2010-02-09  0:11 ` [PATCH 13/14] i2c: Add support for the LPC32XX arch wellsk40 at gmail.com
  2010-02-09  0:11 ` [PATCH 14/14] WATCHDOG: " wellsk40 at gmail.com
  13 siblings, 1 reply; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

The CTRL and IENB registers need to be swapped for the LPC32XX
arch.

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 include/linux/amba/clcd.h |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/include/linux/amba/clcd.h b/include/linux/amba/clcd.h
index 29c0448..8d0d491 100644
--- a/include/linux/amba/clcd.h
+++ b/include/linux/amba/clcd.h
@@ -21,7 +21,8 @@
 #define CLCD_UBAS 		0x00000010
 #define CLCD_LBAS 		0x00000014
 
-#if !defined(CONFIG_ARCH_VERSATILE) && !defined(CONFIG_ARCH_REALVIEW)
+#if !defined(CONFIG_ARCH_VERSATILE) && !defined(CONFIG_ARCH_REALVIEW)\
+	&& !defined(CONFIG_ARCH_LPC32XX)
 #define CLCD_IENB 		0x00000018
 #define CLCD_CNTL 		0x0000001c
 #else
-- 
1.6.6

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

* [PATCH 13/14] i2c: Add support for the LPC32XX arch
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
                   ` (11 preceding siblings ...)
  2010-02-09  0:11 ` [PATCH 12/14] AMBA: CLCD: LPC32XX register swap in the clcd header file wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  2010-02-09  0:11 ` [PATCH 14/14] WATCHDOG: " wellsk40 at gmail.com
  13 siblings, 0 replies; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

Allow the i2c-pnx driver to be reused with the LPC32xx arch.
Changed menu title to include NXP devices

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 drivers/i2c/busses/Kconfig |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 5f318ce..590a441 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -467,8 +467,8 @@ config I2C_PASEMI
 	  Supports the PA Semi PWRficient on-chip SMBus interfaces.
 
 config I2C_PNX
-	tristate "I2C bus support for Philips PNX targets"
-	depends on ARCH_PNX4008
+	tristate "I2C bus support for Philips/NXP devices"
+	depends on ARCH_PNX4008 || ARCH_LPC32XX
 	help
 	  This driver supports the Philips IP3204 I2C IP block master and/or
 	  slave controller
-- 
1.6.6

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

* [PATCH 14/14] WATCHDOG: Add support for the LPC32XX arch
  2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
                   ` (12 preceding siblings ...)
  2010-02-09  0:11 ` [PATCH 13/14] i2c: Add support for the LPC32XX arch wellsk40 at gmail.com
@ 2010-02-09  0:11 ` wellsk40 at gmail.com
  13 siblings, 0 replies; 44+ messages in thread
From: wellsk40 at gmail.com @ 2010-02-09  0:11 UTC (permalink / raw)
  To: linux-arm-kernel

From: Kevin Wells <wellsk40@gmail.com>

Allow the pnx4408 watchdog  driver to be reused with the
LPC32xx arch. Changed menu title to include the LCP32XX
device.

Signed-off-by: Kevin Wells <wellsk40@gmail.com>
---
 drivers/watchdog/Kconfig |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 050ee14..3019415 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -200,11 +200,11 @@ config OMAP_WATCHDOG
 	  here to enable the OMAP1610/OMAP1710/OMAP2420/OMAP3430 watchdog timer.
 
 config PNX4008_WATCHDOG
-	tristate "PNX4008 Watchdog"
-	depends on ARCH_PNX4008
+	tristate "PNX4008/LPC32XX Watchdog"
+	depends on ARCH_PNX4008 || ARCH_LPC32XX
 	help
 	  Say Y here if to include support for the watchdog timer
-	  in the PNX4008 processor.
+	  in the PNX4008 or LPC32XX processors.
 	  This driver can be built as a module by choosing M. The module
 	  will be called pnx4008_wdt.
 
-- 
1.6.6

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

* [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
  2010-02-09  0:11 ` [PATCH 01/14] ARM: LPC32XX: Initial architecture header files wellsk40 at gmail.com
@ 2010-02-09  9:31   ` Uwe Kleine-König
  2010-02-09  9:52     ` Uwe Kleine-König
                       ` (2 more replies)
  0 siblings, 3 replies; 44+ messages in thread
From: Uwe Kleine-König @ 2010-02-09  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hey Kevin,

On Mon, Feb 08, 2010 at 04:11:22PM -0800, wellsk40 at gmail.com wrote:
> From: Kevin Wells <wellsk40@gmail.com>
> 
> Initial header files for the LPC32XX architecture
> 
> Signed-off-by: Kevin Wells <wellsk40@gmail.com>
> ---
>  arch/arm/mach-lpc32xx/include/mach/board.h      |   23 +
>  arch/arm/mach-lpc32xx/include/mach/clkdev.h     |   25 +
>  arch/arm/mach-lpc32xx/include/mach/gpio.h       |   74 +++
>  arch/arm/mach-lpc32xx/include/mach/hardware.h   |   34 ++
>  arch/arm/mach-lpc32xx/include/mach/i2c.h        |   63 ++
>  arch/arm/mach-lpc32xx/include/mach/io.h         |   27 +
>  arch/arm/mach-lpc32xx/include/mach/irqs.h       |  114 ++++
>  arch/arm/mach-lpc32xx/include/mach/memory.h     |   28 +
>  arch/arm/mach-lpc32xx/include/mach/platform.h   |  697 +++++++++++++++++++++++
>  arch/arm/mach-lpc32xx/include/mach/system.h     |   52 ++
>  arch/arm/mach-lpc32xx/include/mach/timex.h      |   29 +
>  arch/arm/mach-lpc32xx/include/mach/uncompress.h |   63 ++
>  arch/arm/mach-lpc32xx/include/mach/vmalloc.h    |   24 +
>  13 files changed, 1253 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-lpc32xx/include/mach/board.h b/arch/arm/mach-lpc32xx/include/mach/board.h
> new file mode 100644
> index 0000000..30424bc
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/board.h
> @@ -0,0 +1,23 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/board.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +
nitpick: there is an empty line too much.

> +#ifndef __ASM_ARCH_BOARD_H
> +#define __ASM_ARCH_BOARD_H
> +
> +#endif
Do you really need this file?

> diff --git a/arch/arm/mach-lpc32xx/include/mach/clkdev.h b/arch/arm/mach-lpc32xx/include/mach/clkdev.h
> new file mode 100644
> index 0000000..9bf0637
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/clkdev.h
> @@ -0,0 +1,25 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/clkdev.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
hmmm, I wonder why you use your nxp address here, but gmail in the
S-o-b.

> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __ASM_ARCH_CLKDEV_H
> +#define __ASM_ARCH_CLKDEV_H
> +
> +#define __clk_get(clk) ({ 1; })
> +#define __clk_put(clk) do { } while (0)
> +
> +#endif
> diff --git a/arch/arm/mach-lpc32xx/include/mach/gpio.h b/arch/arm/mach-lpc32xx/include/mach/gpio.h
> new file mode 100644
> index 0000000..67d03da
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/gpio.h
> @@ -0,0 +1,74 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/gpio.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __ASM_ARCH_GPIO_H
> +#define __ASM_ARCH_GPIO_H
> +
> +#include <asm-generic/gpio.h>
> +
> +/*
> + * Note!
> + * Muxed GP pins need to be setup to the GP state in the board level
> + * code prior to using this driver.
> + * GPI pins : 28xP3 group
> + * GPO pins : 24xP3 group
> + * GPIO pins: 8xP0 group, 24xP1 group, 13xP2 group, 6xP3 group
> + */
> +
> +#define LPC32XX_GPIO_P0_MAX 8
> +#define LPC32XX_GPIO_P1_MAX 24
> +#define LPC32XX_GPIO_P2_MAX 13
> +#define LPC32XX_GPIO_P3_MAX 6
> +#define LPC32XX_GPI_P3_MAX 28
> +#define LPC32XX_GPO_P3_MAX 24
> +
> +#define LPC32XX_GPIO_P0_GRP 0
> +#define LPC32XX_GPIO_P1_GRP (LPC32XX_GPIO_P0_GRP + LPC32XX_GPIO_P0_MAX)
> +#define LPC32XX_GPIO_P2_GRP (LPC32XX_GPIO_P1_GRP + LPC32XX_GPIO_P1_MAX)
> +#define LPC32XX_GPIO_P3_GRP (LPC32XX_GPIO_P2_GRP + LPC32XX_GPIO_P2_MAX)
> +#define LPC32XX_GPI_P3_GRP (LPC32XX_GPIO_P3_GRP + LPC32XX_GPIO_P3_MAX)
> +#define LPC32XX_GPO_P3_GRP (LPC32XX_GPI_P3_GRP + LPC32XX_GPI_P3_MAX)
> +
> +/*
> + * A specific GPIO can be selected with this macro
> + * ie, GPIO_05 can be selected with LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
> + * See the LPC32x0 User's guide for GPIO group numbers
> + */
> +#define LPC32XX_GPIO(x, y) ((x) + (y))
> +
> +static inline int gpio_get_value(unsigned gpio)
> +{
> +	return __gpio_get_value(gpio);
> +}
> +
> +static inline void gpio_set_value(unsigned gpio, int value)
> +{
> +	__gpio_set_value(gpio, value);
> +}
> +
> +static inline int gpio_cansleep(unsigned gpio)
> +{
> +	return __gpio_cansleep(gpio);
> +}
> +
> +static inline int gpio_to_irq(unsigned gpio)
> +{
> +	return __gpio_to_irq(gpio);
> +}
> +
> +#endif
> diff --git a/arch/arm/mach-lpc32xx/include/mach/hardware.h b/arch/arm/mach-lpc32xx/include/mach/hardware.h
> new file mode 100644
> index 0000000..33e1dde
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/hardware.h
> @@ -0,0 +1,34 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/hardware.h
> + *
> + * Copyright (c) 2005 MontaVista Software, Inc. <source@mvista.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __ASM_ARCH_HARDWARE_H
> +#define __ASM_ARCH_HARDWARE_H
> +
> +/*
> + * Start of virtual addresses for IO devices
> + */
> +#define IO_BASE		0xF0000000
> +
> +/*
> + * This macro relies on fact that for all HW i/o addresses bits 20-23 are 0
> + */
> +#define IO_ADDRESS(x)	(((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) |\
> +			 IO_BASE)
> +
> +#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
Is this cast to unsigned long needed?  AFAIK IO_ADDRESS(x) has
type unsigned for x in { 0x0 ... 0xffffffff } (provided that int uses a
32 bit 2s-complement representation).  If unsigned long is really
needed, maybe put it into the IO_ADDRESS macro?

> +#define io_v2p(x)	((((x) & 0x0ff00000) << 4) | ((x) & 0x000fffff))
> +
> +#endif
> diff --git a/arch/arm/mach-lpc32xx/include/mach/i2c.h b/arch/arm/mach-lpc32xx/include/mach/i2c.h
> new file mode 100644
> index 0000000..a2d810b
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/i2c.h
> @@ -0,0 +1,63 @@
> +/*
> + * PNX4008-specific tweaks for I2C IP3204 block
> + *
> + * Author: Vitaly Wool <vwool@ru.mvista.com>
> + *
> + * 2005 (c) MontaVista Software, Inc. This file is licensed under
> + * the terms of the GNU General Public License version 2. This program
> + * is licensed "as is" without any warranty of any kind, whether express
> + * or implied.
> + */
> +
> +#ifndef __ASM_ARCH_I2C_H__
> +#define __ASM_ARCH_I2C_H__
inconsistant macro naming.  The headers above don't end in _H__, only
_H.

> +
> +enum {
> +	mstatus_tdi = 0x00000001,
> +	mstatus_afi = 0x00000002,
> +	mstatus_nai = 0x00000004,
> +	mstatus_drmi = 0x00000008,
> +	mstatus_active = 0x00000020,
> +	mstatus_scl = 0x00000040,
> +	mstatus_sda = 0x00000080,
> +	mstatus_rff = 0x00000100,
> +	mstatus_rfe = 0x00000200,
> +	mstatus_tff = 0x00000400,
> +	mstatus_tfe = 0x00000800,
> +};
> +
> +enum {
> +	mcntrl_tdie = 0x00000001,
> +	mcntrl_afie = 0x00000002,
> +	mcntrl_naie = 0x00000004,
> +	mcntrl_drmie = 0x00000008,
> +	mcntrl_daie = 0x00000020,
> +	mcntrl_rffie = 0x00000040,
> +	mcntrl_tffie = 0x00000080,
> +	mcntrl_reset = 0x00000100,
> +	mcntrl_cdbmode = 0x00000400,
> +};
> +
> +enum {
> +	rw_bit = 1 << 0,
> +	start_bit = 1 << 8,
> +	stop_bit = 1 << 9,
> +};
> +
> +#define I2C_REG_RX(a)	((a)->ioaddr)		/* Rx FIFO reg (RO) */
> +#define I2C_REG_TX(a)	((a)->ioaddr)		/* Tx FIFO reg (WO) */
> +#define I2C_REG_STS(a)	((a)->ioaddr + 0x04)	/* Status reg (RO) */
> +#define I2C_REG_CTL(a)	((a)->ioaddr + 0x08)	/* Ctl reg */
> +#define I2C_REG_CKL(a)	((a)->ioaddr + 0x0c)	/* Clock divider low */
> +#define I2C_REG_CKH(a)	((a)->ioaddr + 0x10)	/* Clock divider high */
> +#define I2C_REG_ADR(a)	((a)->ioaddr + 0x14)	/* I2C address */
> +#define I2C_REG_RFL(a)	((a)->ioaddr + 0x18)	/* Rx FIFO level (RO) */
> +#define I2C_REG_TFL(a)	((a)->ioaddr + 0x1c)	/* Tx FIFO level (RO) */
> +#define I2C_REG_RXB(a)	((a)->ioaddr + 0x20)	/* Num of bytes Rx-ed (RO) */
> +#define I2C_REG_TXB(a)	((a)->ioaddr + 0x24)	/* Num of bytes Tx-ed (RO) */
> +#define I2C_REG_TXS(a)	((a)->ioaddr + 0x28)	/* Tx slave FIFO (RO) */
> +#define I2C_REG_STFL(a)	((a)->ioaddr + 0x2c)	/* Tx slave FIFO level (RO) */
> +
> +#define I2C_CHIP_NAME		"PNX4008-I2C"
> +
> +#endif				/* __ASM_ARCH_I2C_H___ */
nitpick: is i2c.h needed in the first patch?  (Ok Ok, you work for NXP :-)

> diff --git a/arch/arm/mach-lpc32xx/include/mach/io.h b/arch/arm/mach-lpc32xx/include/mach/io.h
> new file mode 100644
> index 0000000..9b59ab5
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/io.h
> @@ -0,0 +1,27 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/io.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __ASM_ARM_ARCH_IO_H
> +#define __ASM_ARM_ARCH_IO_H
> +
> +#define IO_SPACE_LIMIT	0xffffffff
> +
> +#define __io(a)		__typesafe_io(a)
> +#define __mem_pci(a)	(a)
> +
> +#endif
> diff --git a/arch/arm/mach-lpc32xx/include/mach/irqs.h b/arch/arm/mach-lpc32xx/include/mach/irqs.h
> new file mode 100644
> index 0000000..7a78057
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/irqs.h
> @@ -0,0 +1,114 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/irqs.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __ASM_ARM_ARCH_IRQS_H
> +#define __ASM_ARM_ARCH_IRQS_H
> +
> +/*
> + * MIC interrupts
> + */
> +#define IRQ_LPC32XX_SUB1IRQ		0
> +#define IRQ_LPC32XX_SUB2IRQ		1
> +#define IRQ_LPC32XX_PWM3		3
> +#define IRQ_LPC32XX_PWM4		4
> +#define IRQ_LPC32XX_HSTIMER		5
> +#define IRQ_LPC32XX_WATCH		6
> +#define IRQ_LPC32XX_UART_IIR3		7
> +#define IRQ_LPC32XX_UART_IIR4		8
> +#define IRQ_LPC32XX_UART_IIR5		9
> +#define IRQ_LPC32XX_UART_IIR6		10
> +#define IRQ_LPC32XX_FLASH		11
> +#define IRQ_LPC32XX_SD1			13
> +#define IRQ_LPC32XX_LCD			14
> +#define IRQ_LPC32XX_SD0			15
> +#define IRQ_LPC32XX_TIMER0		16
> +#define IRQ_LPC32XX_TIMER1		17
> +#define IRQ_LPC32XX_TIMER2		18
> +#define IRQ_LPC32XX_TIMER3		19
> +#define IRQ_LPC32XX_SSP0		20
> +#define IRQ_LPC32XX_SSP1		21
> +#define IRQ_LPC32XX_I2S0		22
> +#define IRQ_LPC32XX_I2S1		23
> +#define IRQ_LPC32XX_UART_IIR7		24
> +#define IRQ_LPC32XX_UART_IIR2		25
> +#define IRQ_LPC32XX_UART_IIR1		26
> +#define IRQ_LPC32XX_MSTIMER		27
> +#define IRQ_LPC32XX_DMA			28
> +#define IRQ_LPC32XX_ETHERNET		29
> +#define IRQ_LPC32XX_SUB1FIQ		30
> +#define IRQ_LPC32XX_SUB2FIQ		31
> +
> +/*
> + * SIC1 interrupts start at offset 32
> + */
> +#define IRQ_LPC32XX_JTAG_COMM_TX	(32 + 1)
> +#define IRQ_LPC32XX_JTAG_COMM_RX	(32 + 2)
> +#define IRQ_LPC32XX_GPI_11		(32 + 4)
> +#define IRQ_LPC32XX_TS_P		(32 + 6)
> +#define IRQ_LPC32XX_TS_IRQ		(32 + 7)
> +#define IRQ_LPC32XX_TS_AUX		(32 + 8)
> +#define IRQ_LPC32XX_SPI2		(32 + 12)
> +#define IRQ_LPC32XX_PLLUSB		(32 + 13)
> +#define IRQ_LPC32XX_PLLHCLK		(32 + 14)
> +#define IRQ_LPC32XX_PLL397		(32 + 17)
> +#define IRQ_LPC32XX_I2C_2		(32 + 18)
> +#define IRQ_LPC32XX_I2C_1		(32 + 19)
> +#define IRQ_LPC32XX_RTC			(32 + 20)
> +#define IRQ_LPC32XX_KEY			(32 + 22)
> +#define IRQ_LPC32XX_SPI1		(32 + 23)
> +#define IRQ_LPC32XX_SW			(32 + 24)
> +#define IRQ_LPC32XX_USB_OTG_TIMER	(32 + 25)
> +#define IRQ_LPC32XX_USB_OTG_ATX		(32 + 26)
> +#define IRQ_LPC32XX_USB_HOST		(32 + 27)
> +#define IRQ_LPC32XX_USB_DEV_DMA		(32 + 28)
> +#define IRQ_LPC32XX_USB_DEV_LP		(32 + 29)
> +#define IRQ_LPC32XX_USB_DEV_HP		(32 + 30)
> +#define IRQ_LPC32XX_USB_I2C		(32 + 31)
Maybe make these:

	#define LPC32XX_SIC1_IRQ(x)	(32 + (x))
	#define IRQ_LPC32XX_JTAG_COMM_TX	LPC32XX_SIC1_IRQ(1)

?  Then you can use that in lpc32xx_sic1_handler instead of an
equivalent local #define.

> +/*
> + * SIC2 interrupts start at offset 64
> + */
> +#define IRQ_LPC32XX_GPIO_00		(64 + 0)
> +#define IRQ_LPC32XX_GPIO_01		(64 + 1)
> +#define IRQ_LPC32XX_GPIO_02		(64 + 2)
> +#define IRQ_LPC32XX_GPIO_03		(64 + 3)
> +#define IRQ_LPC32XX_GPIO_04		(64 + 4)
> +#define IRQ_LPC32XX_GPIO_05		(64 + 5)
> +#define IRQ_LPC32XX_SPI2_DATAIN		(64 + 6)
> +#define IRQ_LPC32XX_U2_HCTS		(64 + 7)
> +#define IRQ_LPC32XX_P0_P1_IRQ		(64 + 8)
> +#define IRQ_LPC32XX_GPI_08		(64 + 9)
> +#define IRQ_LPC32XX_GPI_09		(64 + 10)
> +#define IRQ_LPC32XX_GPI_19		(64 + 11)
> +#define IRQ_LPC32XX_U7_HCTS		(64 + 12)
> +#define IRQ_LPC32XX_GPI_07		(64 + 15)
> +#define IRQ_LPC32XX_SDIO		(64 + 18)
> +#define IRQ_LPC32XX_U5_RX		(64 + 19)
> +#define IRQ_LPC32XX_SPI1_DATAIN		(64 + 20)
> +#define IRQ_LPC32XX_GPI_00		(64 + 22)
> +#define IRQ_LPC32XX_GPI_01		(64 + 23)
> +#define IRQ_LPC32XX_GPI_02		(64 + 24)
> +#define IRQ_LPC32XX_GPI_03		(64 + 25)
> +#define IRQ_LPC32XX_GPI_04		(64 + 26)
> +#define IRQ_LPC32XX_GPI_05		(64 + 27)
> +#define IRQ_LPC32XX_GPI_06		(64 + 28)
> +#define IRQ_LPC32XX_SYSCLK		(64 + 31)
> +
> +#define NR_IRQS				96
> +
> +#endif
> diff --git a/arch/arm/mach-lpc32xx/include/mach/memory.h b/arch/arm/mach-lpc32xx/include/mach/memory.h
> new file mode 100644
> index 0000000..b4d8156
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/memory.h
> @@ -0,0 +1,28 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/memory.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __ASM_ARCH_MEMORY_H
> +#define __ASM_ARCH_MEMORY_H
> +
> +/*
> + * Physical DRAM offset of bank 0
> + */
> +#define PHYS_OFFSET	UL(0x80000000)
> +
> +#endif
> +
trailing newline

> diff --git a/arch/arm/mach-lpc32xx/include/mach/platform.h b/arch/arm/mach-lpc32xx/include/mach/platform.h
> new file mode 100644
> index 0000000..e01181f
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/platform.h
> @@ -0,0 +1,697 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/platform.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __ASM_ARCH_PLATFORM_H
> +#define __ASM_ARCH_PLATFORM_H
> +
> +#define _REG(x)					(void __iomem *)(io_p2v(x))
> +
> +#define _SBF(f, v)				((v) << (f))
> +#define _BIT(n)					_SBF(n, 1)
> +
> +/*
> + * AHB 0 physical base addresses
> + */
> +#define LPC32XX_SLC_BASE			0x20020000
> +#define LPC32XX_SSP0_BASE			0x20084000
> +#define LPC32XX_SPI1_BASE			0x20088000
> +#define LPC32XX_SSP1_BASE			0x2008C000
> +#define LPC32XX_SPI2_BASE			0x20090000
> +#define LPC32XX_I2S0_BASE			0x20094000
> +#define LPC32XX_SD_BASE				0x20098000
> +#define LPC32XX_I2S1_BASE			0x2009C000
> +#define LPC32XX_MLC_BASE			0x200A8000
> +#define LPC32XX_AHB0_START			LPC32XX_SLC_BASE
> +#define LPC32XX_AHB0_SIZE			((LPC32XX_MLC_BASE -\
> +						LPC32XX_SLC_BASE) + SZ_4K)
As LPC32XX_AHB0_SIZE isn't a nice difference, I don't see the benefit of
not using a plain number here.

> +/*
> + * AHB 1 physical base addresses
> + */
> +#define LPC32XX_DMA_BASE			0x31000000
> +#define LPC32XX_USB_BASE			0x31020000
> +#define LPC32XX_USBH_BASE			0x31020000
> +#define LPC32XX_USB_OTG_BASE			0x31020000
> +#define LPC32XX_OTG_I2C_BASE			0x31020300
> +#define LPC32XX_LCD_BASE			0x31040000
> +#define LPC32XX_ETHERNET_BASE			0x31060000
> +#define LPC32XX_EMC_BASE			0x31080000
> +#define LPC32XX_ETB_CFG_BASE			0x310C0000
> +#define LPC32XX_ETB_DATA_BASE			0x310E0000
> +#define LPC32XX_AHB1_START			LPC32XX_DMA_BASE
> +#define LPC32XX_AHB1_SIZE			((LPC32XX_EMC_BASE -\
> +						LPC32XX_DMA_BASE) + SZ_4K)
> +/*
> + * FAB physical base addresses
> + */
> +#define LPC32XX_CLK_PM_BASE			0x40004000
> +#define LPC32XX_MIC_BASE			0x40008000
> +#define LPC32XX_SIC1_BASE			0x4000C000
> +#define LPC32XX_SIC2_BASE			0x40010000
> +#define LPC32XX_HS_UART1_BASE			0x40014000
> +#define LPC32XX_HS_UART2_BASE			0x40018000
> +#define LPC32XX_HS_UART7_BASE			0x4001C000
> +#define LPC32XX_RTC_BASE			0x40024000
> +#define LPC32XX_RTC_RAM_BASE			0x40024080
> +#define LPC32XX_GPIO_BASE			0x40028000
> +#define LPC32XX_PWM3_BASE			0x4002C000
> +#define LPC32XX_PWM4_BASE			0x40030000
> +#define LPC32XX_MSTIM_BASE			0x40034000
> +#define LPC32XX_HSTIM_BASE			0x40038000
> +#define LPC32XX_WDTIM_BASE			0x4003C000
> +#define LPC32XX_DEBUG_CTRL_BASE			0x40040000
> +#define LPC32XX_TIMER0_BASE			0x40044000
> +#define LPC32XX_ADC_BASE			0x40048000
> +#define LPC32XX_TIMER1_BASE			0x4004C000
> +#define LPC32XX_KSCAN_BASE			0x40050000
> +#define LPC32XX_UART_CTRL_BASE			0x40054000
> +#define LPC32XX_TIMER2_BASE			0x40058000
> +#define LPC32XX_PWM1_BASE			0x4005C000
> +#define LPC32XX_PWM2_BASE			0x4005C004
> +#define LPC32XX_TIMER3_BASE			0x40060000
> +
> +/*
> + * APB physical base addresses
> + */
> +#define LPC32XX_UART3_BASE			0x40080000
> +#define LPC32XX_UART4_BASE			0x40088000
> +#define LPC32XX_UART5_BASE			0x40090000
> +#define LPC32XX_UART6_BASE			0x40098000
> +#define LPC32XX_I2C1_BASE			0x400A0000
> +#define LPC32XX_I2C2_BASE			0x400A8000
> +
> +/*
> + * FAB and APB base and sizing
> + */
> +#define LPC32XX_FABAPB_START			LPC32XX_CLK_PM_BASE
> +#define LPC32XX_FABAPB_SIZE			((LPC32XX_I2C2_BASE -\
> +						LPC32XX_CLK_PM_BASE) + SZ_4K)
> +
> +/*
> + * Internal memory Bases
> + */
> +#define LPC32XX_IRAM_BASE			0x08000000
> +#define LPC32XX_IROM_BASE			0x0C000000
> +
> +/*
> + * External Static Memory Bank Address Space Bases
> + */
> +#define LPC32XX_EMC_CS0_BASE			0xE0000000
> +#define LPC32XX_EMC_CS1_BASE			0xE1000000
> +#define LPC32XX_EMC_CS2_BASE			0xE2000000
> +#define LPC32XX_EMC_CS3_BASE			0xE3000000
> +
> +/*
> + * External SDRAM Memory Bank Address Space Bases
> + */
> +#define LPC32XX_EMC_DYCS0_BASE			0x80000000
> +#define LPC32XX_EMC_DYCS1_BASE			0xA0000000
> +
> +/*
> + * Clock and crystal information
> + */
> +#define LPC32XX_MAIN_OSC_FREQ			13000000
> +#define LPC32XX_CLOCK_OSC_FREQ			32768
> +
> +/*
> + * Clock and Power control register offsets
> + */
> +#define _PMREG(x)				_REG(LPC32XX_CLK_PM_BASE + (x))
> +#define LPC32XX_CLKPWR_DEBUG_CTRL		_PMREG(0x000)
> +#define LPC32XX_CLKPWR_BOOTMAP			_PMREG(0x014)
> +#define LPC32XX_CLKPWR_P01_ER			_PMREG(0x018)
> +#define LPC32XX_CLKPWR_USBCLK_PDIV		_PMREG(0x01C)
> +#define LPC32XX_CLKPWR_INT_ER			_PMREG(0x020)
> +#define LPC32XX_CLKPWR_INT_RS			_PMREG(0x024)
> +#define LPC32XX_CLKPWR_INT_SR			_PMREG(0x028)
> +#define LPC32XX_CLKPWR_INT_AP			_PMREG(0x02C)
> +#define LPC32XX_CLKPWR_PIN_ER			_PMREG(0x030)
> +#define LPC32XX_CLKPWR_PIN_RS			_PMREG(0x034)
> +#define LPC32XX_CLKPWR_PIN_SR			_PMREG(0x038)
> +#define LPC32XX_CLKPWR_PIN_AP			_PMREG(0x03C)
> +#define LPC32XX_CLKPWR_HCLK_DIV			_PMREG(0x040)
> +#define LPC32XX_CLKPWR_PWR_CTRL			_PMREG(0x044)
> +#define LPC32XX_CLKPWR_PLL397_CTRL		_PMREG(0x048)
> +#define LPC32XX_CLKPWR_MAIN_OSC_CTRL		_PMREG(0x04C)
> +#define LPC32XX_CLKPWR_SYSCLK_CTRL		_PMREG(0x050)
> +#define LPC32XX_CLKPWR_LCDCLK_CTRL		_PMREG(0x054)
> +#define LPC32XX_CLKPWR_HCLKPLL_CTRL		_PMREG(0x058)
> +#define LPC32XX_CLKPWR_ADC_CLK_CTRL_1		_PMREG(0x060)
> +#define LPC32XX_CLKPWR_USB_CTRL			_PMREG(0x064)
> +#define LPC32XX_CLKPWR_SDRAMCLK_CTRL		_PMREG(0x068)
> +#define LPC32XX_CLKPWR_DDR_LAP_NOM		_PMREG(0x06C)
> +#define LPC32XX_CLKPWR_DDR_LAP_COUNT		_PMREG(0x070)
> +#define LPC32XX_CLKPWR_DDR_LAP_DELAY		_PMREG(0x074)
> +#define LPC32XX_CLKPWR_SSP_CLK_CTRL		_PMREG(0x078)
> +#define LPC32XX_CLKPWR_I2S_CLK_CTRL		_PMREG(0x07C)
> +#define LPC32XX_CLKPWR_MS_CTRL			_PMREG(0x080)
> +#define LPC32XX_CLKPWR_MACCLK_CTRL		_PMREG(0x090)
> +#define LPC32XX_CLKPWR_TEST_CLK_SEL		_PMREG(0x0A4)
> +#define LPC32XX_CLKPWR_SFW_INT			_PMREG(0x0A8)
> +#define LPC32XX_CLKPWR_I2C_CLK_CTRL		_PMREG(0x0AC)
> +#define LPC32XX_CLKPWR_KEY_CLK_CTRL		_PMREG(0x0B0)
> +#define LPC32XX_CLKPWR_ADC_CLK_CTRL		_PMREG(0x0B4)
> +#define LPC32XX_CLKPWR_PWM_CLK_CTRL		_PMREG(0x0B8)
> +#define LPC32XX_CLKPWR_TIMER_CLK_CTRL		_PMREG(0x0BC)
> +#define LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1	_PMREG(0x0C0)
> +#define LPC32XX_CLKPWR_SPI_CLK_CTRL		_PMREG(0x0C4)
> +#define LPC32XX_CLKPWR_NAND_CLK_CTRL		_PMREG(0x0C8)
> +#define LPC32XX_CLKPWR_UART3_CLK_CTRL		_PMREG(0x0D0)
> +#define LPC32XX_CLKPWR_UART4_CLK_CTRL		_PMREG(0x0D4)
> +#define LPC32XX_CLKPWR_UART5_CLK_CTRL		_PMREG(0x0D8)
> +#define LPC32XX_CLKPWR_UART6_CLK_CTRL		_PMREG(0x0DC)
> +#define LPC32XX_CLKPWR_IRDA_CLK_CTRL		_PMREG(0x0E0)
> +#define LPC32XX_CLKPWR_UART_CLK_CTRL		_PMREG(0x0E4)
> +#define LPC32XX_CLKPWR_DMA_CLK_CTRL		_PMREG(0x0E8)
> +#define LPC32XX_CLKPWR_AUTOCLOCK		_PMREG(0x0EC)
> +#define LPC32XX_CLKPWR_DEVID(x)			_PMREG(0x130 + (x))
> +
> +/*
> + * clkpwr_debug_ctrl register definitions
> +*/
> +#define LPC32XX_CLKPWR_VFP_CLOCK_ENABLE_BIT	_BIT(4)
> +
> +/*
> + * clkpwr_bootmap register definitions
> + */
> +#define LPC32XX_CLKPWR_BOOTMAP_SEL_BIT		_BIT(1)
> +
> +/*
> + * clkpwr_start_gpio register bit definitions
> + */
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO23_BIT	_BIT(31)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO22_BIT	_BIT(30)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO21_BIT	_BIT(29)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO20_BIT	_BIT(28)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO19_BIT	_BIT(27)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO18_BIT	_BIT(26)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO17_BIT	_BIT(25)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO16_BIT	_BIT(24)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO15_BIT	_BIT(23)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO14_BIT	_BIT(22)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO13_BIT	_BIT(21)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO12_BIT	_BIT(20)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO11_BIT	_BIT(19)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO10_BIT	_BIT(18)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO9_BIT	_BIT(17)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO8_BIT	_BIT(16)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO7_BIT	_BIT(15)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO6_BIT	_BIT(14)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO5_BIT	_BIT(13)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO4_BIT	_BIT(12)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO3_BIT	_BIT(11)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO2_BIT	_BIT(10)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO1_BIT	_BIT(9)
> +#define LPC32XX_CLKPWR_GPIOSRC_P1IO0_BIT	_BIT(8)
> +#define LPC32XX_CLKPWR_GPIOSRC_P0IO7_BIT	_BIT(7)
> +#define LPC32XX_CLKPWR_GPIOSRC_P0IO6_BIT	_BIT(6)
> +#define LPC32XX_CLKPWR_GPIOSRC_P0IO5_BIT	_BIT(5)
> +#define LPC32XX_CLKPWR_GPIOSRC_P0IO4_BIT	_BIT(4)
> +#define LPC32XX_CLKPWR_GPIOSRC_P0IO3_BIT	_BIT(3)
> +#define LPC32XX_CLKPWR_GPIOSRC_P0IO2_BIT	_BIT(2)
> +#define LPC32XX_CLKPWR_GPIOSRC_P0IO1_BIT	_BIT(1)
> +#define LPC32XX_CLKPWR_GPIOSRC_P0IO0_BIT	_BIT(0)
> +
> +/*
> + * clkpwr_usbclk_pdiv register definitions
> + */
> +#define LPC32XX_CLKPWR_SET_PLL_USBPDIV(n)	((n) & 0xF)
> +#define LPC32XX_CLKPWR_USBPDIV_PLL_MASK		0xF
are these two 0xf the same?  If so, you can define
LPC32XX_CLKPWR_SET_PLL_USBPDIV without hardcoding it?

> +
> +/*
> + * clkpwr_start_int, clkpwr_start_raw_sts_int, clkpwr_start_sts_int,
> + * clkpwr_start_pol_int, register bit definitions
> + */
> +#define LPC32XX_CLKPWR_INTSRC_ADC_BIT		_BIT(31)
> +#define LPC32XX_CLKPWR_INTSRC_TS_P_BIT		_BIT(30)
> +#define LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT	_BIT(29)
> +#define LPC32XX_CLKPWR_INTSRC_USBAHNEEDCLK_BIT	_BIT(26)
> +#define LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT	_BIT(25)
> +#define LPC32XX_CLKPWR_INTSRC_RTC_BIT		_BIT(24)
> +#define LPC32XX_CLKPWR_INTSRC_USBNEEDCLK_BIT	_BIT(23)
> +#define LPC32XX_CLKPWR_INTSRC_USB_BIT		_BIT(22)
> +#define LPC32XX_CLKPWR_INTSRC_I2C_BIT		_BIT(21)
> +#define LPC32XX_CLKPWR_INTSRC_USBOTGTIMER_BIT	_BIT(20)
> +#define LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT	_BIT(19)
> +#define LPC32XX_CLKPWR_INTSRC_KEY_BIT		_BIT(16)
> +#define LPC32XX_CLKPWR_INTSRC_MAC_BIT		_BIT(7)
> +#define LPC32XX_CLKPWR_INTSRC_P0P1_BIT		_BIT(6)
> +#define LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT	_BIT(5)
> +#define LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT	_BIT(4)
> +#define LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT	_BIT(3)
> +#define LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT	_BIT(2)
> +#define LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT	_BIT(1)
> +#define LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT	_BIT(0)
> +
> +/*
> + * clkpwr_start_pin, clkpwr_start_raw_sts_pin, clkpwr_start_sts_pin,
> + * clkpwr_start_pol_pin register bit definitions
> + */
> +#define LPC32XX_CLKPWR_EXTSRC_U7_RX_BIT		_BIT(31)
> +#define LPC32XX_CLKPWR_EXTSRC_U7_HCTS_BIT	_BIT(30)
> +#define LPC32XX_CLKPWR_EXTSRC_U6_IRRX_BIT	_BIT(28)
> +#define LPC32XX_CLKPWR_EXTSRC_U5_RX_BIT		_BIT(26)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_28_BIT	_BIT(25)
> +#define LPC32XX_CLKPWR_EXTSRC_U3_RX_BIT		_BIT(24)
> +#define LPC32XX_CLKPWR_EXTSRC_U2_HCTS_BIT	_BIT(23)
> +#define LPC32XX_CLKPWR_EXTSRC_U2_RX_BIT		_BIT(22)
> +#define LPC32XX_CLKPWR_EXTSRC_U1_RX_BIT		_BIT(21)
> +#define LPC32XX_CLKPWR_EXTSRC_MSDIO_INT_BIT	_BIT(18)
> +#define LPC32XX_CLKPWR_EXTSRC_MSDIO_SRT_BIT	_BIT(17)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT	_BIT(16)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_05_BIT	_BIT(15)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_04_BIT	_BIT(14)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_03_BIT	_BIT(13)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_02_BIT	_BIT(12)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_01_BIT	_BIT(11)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_00_BIT	_BIT(10)
> +#define LPC32XX_CLKPWR_EXTSRC_SYSCLKEN_BIT	_BIT(9)
> +#define LPC32XX_CLKPWR_EXTSRC_SPI1_DATIN_BIT	_BIT(8)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT	_BIT(7)
> +#define LPC32XX_CLKPWR_EXTSRC_SPI2_DATIN_BIT	_BIT(6)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_19_BIT	_BIT(5)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_09_BIT	_BIT(4)
> +#define LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT	_BIT(3)
> +
> +/*
> + * clkpwr_hclk_div register definitions
> + */
> +#define LPC32XX_CLKPWR_HCLKDIV_DDRCLK_STOP	(0x0 << 7)
> +#define LPC32XX_CLKPWR_HCLKDIV_DDRCLK_NORM	(0x1 << 7)
> +#define LPC32XX_CLKPWR_HCLKDIV_DDRCLK_HALF	(0x2 << 7)
> +#define LPC32XX_CLKPWR_HCLKDIV_PCLK_DIV(n)	(((n) & 0x1F) << 2)
> +#define LPC32XX_CLKPWR_HCLKDIV_DIV_2POW(n)	((n) & 0x3)
> +
> +/*
> + * clkpwr_pwr_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_CTRL_FORCE_PCLK		_BIT(10)
> +#define LPC32XX_CLKPWR_SDRAM_SELF_RFSH		_BIT(9)
> +#define LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH	_BIT(8)
> +#define LPC32XX_CLKPWR_AUTO_SDRAM_SELF_RFSH	_BIT(7)
> +#define LPC32XX_CLKPWR_HIGHCORE_STATE_BIT	_BIT(5)
> +#define LPC32XX_CLKPWR_SYSCLKEN_STATE_BIT	_BIT(4)
> +#define LPC32XX_CLKPWR_SYSCLKEN_GPIO_EN		_BIT(3)
> +#define LPC32XX_CLKPWR_SELECT_RUN_MODE		_BIT(2)
> +#define LPC32XX_CLKPWR_HIGHCORE_GPIO_EN		_BIT(1)
> +#define LPC32XX_CLKPWR_STOP_MODE_CTRL		_BIT(0)
> +
> +/*
> + * clkpwr_pll397_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_PLL397_MSLOCK_STS	_BIT(10)
> +#define LPC32XX_CLKPWR_PLL397_BYPASS		_BIT(9)
> +#define LPC32XX_CLKPWR_PLL397_BIAS_NORM		0x000
> +#define LPC32XX_CLKPWR_PLL397_BIAS_N12_5	0x040
> +#define LPC32XX_CLKPWR_PLL397_BIAS_N25		0x080
> +#define LPC32XX_CLKPWR_PLL397_BIAS_N37_5	0x0C0
> +#define LPC32XX_CLKPWR_PLL397_BIAS_P12_5	0x100
> +#define LPC32XX_CLKPWR_PLL397_BIAS_P25		0x140
> +#define LPC32XX_CLKPWR_PLL397_BIAS_P37_5	0x180
> +#define LPC32XX_CLKPWR_PLL397_BIAS_P50		0x1C0
> +#define LPC32XX_CLKPWR_PLL397_BIAS_MASK		0x1C0
> +#define LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS	_BIT(1)
> +#define LPC32XX_CLKPWR_SYSCTRL_PLL397_STS	_BIT(0)
> +
> +/*
> + * clkpwr_main_osc_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_MOSC_ADD_CAP(n)		(((n) & 0x7F) << 2)
> +#define LPC32XX_CLKPWR_MOSC_CAP_MASK		(0x7F << 2)
> +#define LPC32XX_CLKPWR_TEST_MODE		_BIT(1)
> +#define LPC32XX_CLKPWR_MOSC_DISABLE		_BIT(0)
> +
> +/*
> + * clkpwr_sysclk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_SYSCTRL_BP_TRIG(n)	(((n) & 0x3FF) << 2)
> +#define LPC32XX_CLKPWR_SYSCTRL_BP_MASK		(0x3FF << 2)
> +#define LPC32XX_CLKPWR_SYSCTRL_USEPLL397	_BIT(1)
> +#define LPC32XX_CLKPWR_SYSCTRL_SYSCLKMUX	_BIT(0)
> +
> +/*
> + * clkpwr_lcdclk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT12	0x000
> +#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16	0x040
> +#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT15	0x080
> +#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT24	0x0C0
> +#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_STN4M	0x100
> +#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_STN8C	0x140
> +#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_DSTN4M	0x180
> +#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_DSTN8C	0x1C0
> +#define LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK	0x01C0
> +#define LPC32XX_CLKPWR_LCDCTRL_CLK_EN		0x020
> +#define LPC32XX_CLKPWR_LCDCTRL_SET_PSCALE(n)	((n - 1) & 0x1F)
> +#define LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK	0x001F
> +
> +/*
> + * clkpwr_hclkpll_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_HCLKPLL_POWER_UP		_BIT(16)
> +#define LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS	_BIT(15)
> +#define LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS	_BIT(14)
> +#define LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK	_BIT(13)
> +#define LPC32XX_CLKPWR_HCLKPLL_POSTDIV_2POW(n)	(((n) & 0x3) << 11)
> +#define LPC32XX_CLKPWR_HCLKPLL_PREDIV_PLUS1(n)	(((n) & 0x3) << 9)
> +#define LPC32XX_CLKPWR_HCLKPLL_PLLM(n)		(((n) & 0xFF) << 1)
> +#define LPC32XX_CLKPWR_HCLKPLL_PLL_STS		_BIT(0)
> +
> +/*
> + * clkpwr_adc_clk_ctrl_1 register definitions
> + */
> +#define LPC32XX_CLKPWR_ADCCTRL1_RTDIV(n)	(((n) & 0xFF) << 0)
> +#define LPC32XX_CLKPWR_ADCCTRL1_PCLK_SEL	_BIT(8)
> +
> +/*
> + * clkpwr_usb_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_USBCTRL_HCLK_EN		_BIT(24)
> +#define LPC32XX_CLKPWR_USBCTRL_USBI2C_EN	_BIT(23)
> +#define LPC32XX_CLKPWR_USBCTRL_USBDVND_EN	_BIT(22)
> +#define LPC32XX_CLKPWR_USBCTRL_USBHSTND_EN	_BIT(21)
> +#define LPC32XX_CLKPWR_USBCTRL_PU_ADD		(0x0 << 19)
> +#define LPC32XX_CLKPWR_USBCTRL_BUS_KEEPER	(0x1 << 19)
> +#define LPC32XX_CLKPWR_USBCTRL_PD_ADD		(0x3 << 19)
> +#define LPC32XX_CLKPWR_USBCTRL_CLK_EN2		_BIT(18)
> +#define LPC32XX_CLKPWR_USBCTRL_CLK_EN1		_BIT(17)
> +#define LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP	_BIT(16)
> +#define LPC32XX_CLKPWR_USBCTRL_CCO_BYPASS	_BIT(15)
> +#define LPC32XX_CLKPWR_USBCTRL_POSTDIV_BYPASS	_BIT(14)
> +#define LPC32XX_CLKPWR_USBCTRL_FDBK_SEL_FCLK	_BIT(13)
> +#define LPC32XX_CLKPWR_USBCTRL_POSTDIV_2POW(n)	(((n) & 0x3) << 11)
> +#define LPC32XX_CLKPWR_USBCTRL_PREDIV_PLUS1(n)	(((n) & 0x3) << 9)
> +#define LPC32XX_CLKPWR_USBCTRL_FDBK_PLUS1(n)	(((n) & 0xFF) << 1)
> +#define LPC32XX_CLKPWR_USBCTRL_PLL_STS		_BIT(0)
> +
> +/*
> + * clkpwr_sdramclk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_SDRCLK_FASTSLEW_CLK	_BIT(22)
> +#define LPC32XX_CLKPWR_SDRCLK_FASTSLEW		_BIT(21)
> +#define LPC32XX_CLKPWR_SDRCLK_FASTSLEW_DAT	_BIT(20)
> +#define LPC32XX_CLKPWR_SDRCLK_SW_DDR_RESET	_BIT(19)
> +#define LPC32XX_CLKPWR_SDRCLK_HCLK_DLY(n)	(((n) & 0x1F) << 14)
> +#define LPC32XX_CLKPWR_SDRCLK_DLY_ADDR_STS	_BIT(13)
> +#define LPC32XX_CLKPWR_SDRCLK_SENS_FACT(n)	(((n) & 0x7) << 10)
> +#define LPC32XX_CLKPWR_SDRCLK_USE_CAL		_BIT(9)
> +#define LPC32XX_CLKPWR_SDRCLK_DO_CAL		_BIT(8)
> +#define LPC32XX_CLKPWR_SDRCLK_CAL_ON_RTC	_BIT(7)
> +#define LPC32XX_CLKPWR_SDRCLK_DQS_DLY(n)	(((n) & 0x1F) << 2)
> +#define LPC32XX_CLKPWR_SDRCLK_USE_DDR		_BIT(1)
> +#define LPC32XX_CLKPWR_SDRCLK_CLK_DIS		_BIT(0)
> +
> +/*
> + * clkpwr_ssp_blk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP1RX	_BIT(5)
> +#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP1TX	_BIT(4)
> +#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP0RX	_BIT(3)
> +#define LPC32XX_CLKPWR_SSPCTRL_DMA_SSP0TX	_BIT(2)
> +#define LPC32XX_CLKPWR_SSPCTRL_SSPCLK1_EN	_BIT(1)
> +#define LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN	_BIT(0)
> +
> +/*
> + * clkpwr_i2s_clk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_I2SCTRL_I2S1_RX_FOR_TX	_BIT(6)
> +#define LPC32XX_CLKPWR_I2SCTRL_I2S1_TX_FOR_RX	_BIT(5)
> +#define LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA	_BIT(4)
> +#define LPC32XX_CLKPWR_I2SCTRL_I2S0_RX_FOR_TX	_BIT(3)
> +#define LPC32XX_CLKPWR_I2SCTRL_I2S0_TX_FOR_RX	_BIT(2)
> +#define LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN	_BIT(1)
> +#define LPC32XX_CLKPWR_I2SCTRL_I2SCLK0_EN	_BIT(0)
> +
> +/*
> + * clkpwr_ms_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_MSCARD_MSDIO_PIN_DIS	_BIT(10)
> +#define LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN	_BIT(9)
> +#define LPC32XX_CLKPWR_MSCARD_MSDIO23_DIS	_BIT(8)
> +#define LPC32XX_CLKPWR_MSCARD_MSDIO1_DIS	_BIT(7)
> +#define LPC32XX_CLKPWR_MSCARD_MSDIO0_DIS	_BIT(6)
> +#define LPC32XX_CLKPWR_MSCARD_SDCARD_EN		_BIT(5)
> +#define LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(n)	((n) & 0xF)
> +
> +/*
> + * clkpwr_macclk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_MACCTRL_NO_ENET_PIS	0x00
> +#define LPC32XX_CLKPWR_MACCTRL_USE_MII_PINS	0x08
> +#define LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS	0x18
> +#define LPC32XX_CLKPWR_MACCTRL_PINS_MSK		0x18
> +#define LPC32XX_CLKPWR_MACCTRL_DMACLK_EN	_BIT(2)
> +#define LPC32XX_CLKPWR_MACCTRL_MMIOCLK_EN	_BIT(1)
> +#define LPC32XX_CLKPWR_MACCTRL_HRCCLK_EN	_BIT(0)
> +
> +/*
> + * clkpwr_test_clk_sel register definitions
> + */
> +#define LPC32XX_CLKPWR_TESTCLK1_SEL_PERCLK	(0x0 << 5)
> +#define LPC32XX_CLKPWR_TESTCLK1_SEL_RTC		(0x1 << 5)
> +#define LPC32XX_CLKPWR_TESTCLK1_SEL_MOSC	(0x2 << 5)
> +#define LPC32XX_CLKPWR_TESTCLK1_SEL_MASK	(0x3 << 5)
> +#define LPC32XX_CLKPWR_TESTCLK_TESTCLK1_EN	_BIT(4)
> +#define LPC32XX_CLKPWR_TESTCLK2_SEL_HCLK	(0x0 << 1)
> +#define LPC32XX_CLKPWR_TESTCLK2_SEL_PERCLK	(0x1 << 1)
> +#define LPC32XX_CLKPWR_TESTCLK2_SEL_USBCLK	(0x2 << 1)
> +#define LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC	(0x5 << 1)
> +#define LPC32XX_CLKPWR_TESTCLK2_SEL_PLL397	(0x7 << 1)
> +#define LPC32XX_CLKPWR_TESTCLK2_SEL_MASK	(0x7 << 1)
> +#define LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN	_BIT(0)
> +
> +/*
> + * clkpwr_sw_int register definitions
> + */
> +#define LPC32XX_CLKPWR_SW_INT(n)		(_BIT(0) | (((n) & 0x7F) << 1))
> +#define LPC32XX_CLKPWR_SW_GET_ARG(n)		(((n) & 0xFE) >> 1)
> +
> +/*
> + * clkpwr_i2c_clk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE	_BIT(4)
> +#define LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE	_BIT(3)
> +#define LPC32XX_CLKPWR_I2CCLK_I2C1HI_DRIVE	_BIT(2)
> +#define LPC32XX_CLKPWR_I2CCLK_I2C2CLK_EN	_BIT(1)
> +#define LPC32XX_CLKPWR_I2CCLK_I2C1CLK_EN	_BIT(0)
> +
> +/*
> + * clkpwr_key_clk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_KEYCLKCTRL_CLK_EN	0x1
> +
> +/*
> + * clkpwr_adc_clk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_ADC32CLKCTRL_CLK_EN	0x1
> +
> +/*
> + * clkpwr_pwm_clk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_PWMCLK_PWM2_DIV(n)	(((n) & 0xF) << 8)
> +#define LPC32XX_CLKPWR_PWMCLK_PWM1_DIV(n)	(((n) & 0xF) << 4)
> +#define LPC32XX_CLKPWR_PWMCLK_PWM2SEL_PCLK	0x8
> +#define LPC32XX_CLKPWR_PWMCLK_PWM2CLK_EN	0x4
> +#define LPC32XX_CLKPWR_PWMCLK_PWM1SEL_PCLK	0x2
> +#define LPC32XX_CLKPWR_PWMCLK_PWM1CLK_EN	0x1
> +
> +/*
> + * clkpwr_timer_clk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_PWMCLK_HSTIMER_EN	0x2
> +#define LPC32XX_CLKPWR_PWMCLK_WDOG_EN		0x1
> +
> +/*
> + * clkpwr_timers_pwms_clk_ctrl_1 register definitions
> + */
> +#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER3_EN	0x20
> +#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER2_EN	0x10
> +#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN	0x08
> +#define LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN	0x04
> +#define LPC32XX_CLKPWR_TMRPWMCLK_PWM4_EN	0x02
> +#define LPC32XX_CLKPWR_TMRPWMCLK_PWM3_EN	0x01
> +
> +/*
> + * clkpwr_spi_clk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_SPICLK_SET_SPI2DATIO	0x80
> +#define LPC32XX_CLKPWR_SPICLK_SET_SPI2CLK	0x40
> +#define LPC32XX_CLKPWR_SPICLK_USE_SPI2		0x20
> +#define LPC32XX_CLKPWR_SPICLK_SPI2CLK_EN	0x10
> +#define LPC32XX_CLKPWR_SPICLK_SET_SPI1DATIO	0x08
> +#define LPC32XX_CLKPWR_SPICLK_SET_SPI1CLK	0x04
> +#define LPC32XX_CLKPWR_SPICLK_USE_SPI1		0x02
> +#define LPC32XX_CLKPWR_SPICLK_SPI1CLK_EN	0x01
> +
> +/*
> + * clkpwr_nand_clk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_NANDCLK_INTSEL_MLC	0x20
> +#define LPC32XX_CLKPWR_NANDCLK_DMA_RNB		0x10
> +#define LPC32XX_CLKPWR_NANDCLK_DMA_INT		0x08
> +#define LPC32XX_CLKPWR_NANDCLK_SEL_SLC		0x04
> +#define LPC32XX_CLKPWR_NANDCLK_MLCCLK_EN	0x02
> +#define LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN	0x01
> +
> +/*
> + * clkpwr_uart3_clk_ctrl, clkpwr_uart4_clk_ctrl, clkpwr_uart5_clk_ctrl
> + * and clkpwr_uart6_clk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_UART_Y_DIV(y)		((y) & 0xFF)
> +#define LPC32XX_CLKPWR_UART_X_DIV(x)		(((x) & 0xFF) << 8)
> +#define LPC32XX_CLKPWR_UART_USE_HCLK		_BIT(16)
> +
> +/*
> + * clkpwr_irda_clk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_IRDA_Y_DIV(y)		((y) & 0xFF)
> +#define LPC32XX_CLKPWR_IRDA_X_DIV(x)		(((x) & 0xFF) << 8)
> +
> +/*
> + * clkpwr_uart_clk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_UARTCLKCTRL_UART6_EN	_BIT(3)
> +#define LPC32XX_CLKPWR_UARTCLKCTRL_UART5_EN	_BIT(2)
> +#define LPC32XX_CLKPWR_UARTCLKCTRL_UART4_EN	_BIT(1)
> +#define LPC32XX_CLKPWR_UARTCLKCTRL_UART3_EN	_BIT(0)
> +
> +/*
> + * clkpwr_dmaclk_ctrl register definitions
> + */
> +#define LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN	0x1
> +
> +/*
> + * clkpwr_autoclock register definitions
> + */
> +#define LPC32XX_CLKPWR_AUTOCLK_USB_EN		0x40
> +#define LPC32XX_CLKPWR_AUTOCLK_IRAM_EN		0x02
> +#define LPC32XX_CLKPWR_AUTOCLK_IROM_EN		0x01
> +
> +/*
> + * Interrupt controller register offsets
> + */
> +#define LPC32XX_INTC_MASK(x)			_REG((x) + 0x00)
> +#define LPC32XX_INTC_RAW_STAT(x)		_REG((x) + 0x04)
> +#define LPC32XX_INTC_STAT(x)			_REG((x) + 0x08)
> +#define LPC32XX_INTC_POLAR(x)			_REG((x) + 0x0C)
> +#define LPC32XX_INTC_ACT_TYPE(x)		_REG((x) + 0x10)
> +#define LPC32XX_INTC_TYPE(x)			_REG((x) + 0x14)
> +
> +/*
> + * Timer/counter register offsets
> + */
> +#define LCP32XX_TIMER_IR(x)			_REG((x) + 0x00)
> +#define LCP32XX_TIMER_TCR(x)			_REG((x) + 0x04)
> +#define LCP32XX_TIMER_TC(x)			_REG((x) + 0x08)
> +#define LCP32XX_TIMER_PR(x)			_REG((x) + 0x0C)
> +#define LCP32XX_TIMER_PC(x)			_REG((x) + 0x10)
> +#define LCP32XX_TIMER_MCR(x)			_REG((x) + 0x14)
> +#define LCP32XX_TIMER_MR0(x)			_REG((x) + 0x18)
> +#define LCP32XX_TIMER_MR1(x)			_REG((x) + 0x1C)
> +#define LCP32XX_TIMER_MR2(x)			_REG((x) + 0x20)
> +#define LCP32XX_TIMER_MR3(x)			_REG((x) + 0x24)
> +#define LCP32XX_TIMER_CCR(x)			_REG((x) + 0x28)
> +#define LCP32XX_TIMER_CR0(x)			_REG((x) + 0x2C)
> +#define LCP32XX_TIMER_CR1(x)			_REG((x) + 0x30)
> +#define LCP32XX_TIMER_CR2(x)			_REG((x) + 0x34)
> +#define LCP32XX_TIMER_CR3(x)			_REG((x) + 0x38)
> +#define LCP32XX_TIMER_EMR(x)			_REG((x) + 0x3C)
> +#define LCP32XX_TIMER_CTCR(x)			_REG((x) + 0x70)
> +
> +/*
> + * ir register definitions
> + */
> +#define LCP32XX_TIMER_CNTR_MTCH_BIT(n)		(1 << ((n) & 0x3))
> +#define LCP32XX_TIMER_CNTR_CAPT_BIT(n)		(1 << (4 + ((n) & 0x3)))
> +
> +/*
> + * tcr register definitions
> + */
> +#define LCP32XX_TIMER_CNTR_TCR_EN		0x1
> +#define LCP32XX_TIMER_CNTR_TCR_RESET		0x2
> +
> +/*
> + * mcr register definitions
> + */
> +#define LCP32XX_TIMER_CNTR_MCR_MTCH(n)		(0x1 << ((n) * 3))
> +#define LCP32XX_TIMER_CNTR_MCR_RESET(n)		(0x1 << (((n) * 3) + 1))
> +#define LCP32XX_TIMER_CNTR_MCR_STOP(n)		(0x1 << (((n) * 3) + 2))
> +
> +/*
> + * Standard UART register offsets
> + */
> +#define LPC32XX_UART_DLL_FIFO(x)		_REG((x) + 0x00)
> +#define LPC32XX_UART_DLM_IER(x)			_REG((x) + 0x04)
> +#define LPC32XX_UART_IIR_FCR(x)			_REG((x) + 0x08)
> +#define LPC32XX_UART_LCR(x)			_REG((x) + 0x0C)
> +#define LPC32XX_UART_MODEM_CTRL(x)		_REG((x) + 0x10)
> +#define LPC32XX_UART_LSR(x)			_REG((x) + 0x14)
> +#define LPC32XX_UART_MODEM_STATUS(x)		_REG((x) + 0x18)
> +#define LPC32XX_UART_RXLEV(x)			_REG((x) + 0x1C)
> +
> +/*
> + * UART control structure offsets
> + */
> +#define _UCREG(x)				_REG(LPC32XX_UART_CTRL_BASE +\
> +						(x))
> +#define LPC32XX_UARTCTL_CTRL			_UCREG(0x00)
> +#define LPC32XX_UARTCTL_CLKMODE			_UCREG(0x04)
> +#define LPC32XX_UARTCTL_CLOOP			_UCREG(0x08)
> +
> +/*
> + * ctrl register definitions
> + */
> +#define LPC32XX_UART_U3_MD_CTRL_EN		_BIT(11)
> +#define LPC32XX_UART_IRRX6_INV_EN		_BIT(10)
> +#define LPC32XX_UART_HDPX_EN			_BIT(9)
> +#define LPC32XX_UART_UART6_IRDAMOD_BYPASS	_BIT(5)
> +#define LPC32XX_RT_IRTX6_INV_EN			_BIT(4)
> +#define LPC32XX_RT_IRTX6_INV_MIR_EN		_BIT(3)
> +#define LPC32XX_RT_RX_IRPULSE_3_16_115K		_BIT(2)
> +#define LPC32XX_RT_TX_IRPULSE_3_16_115K		_BIT(1)
> +#define LPC32XX_UART_U5_ROUTE_TO_USB		_BIT(0)
> +
> +/*
> + * clkmode register definitions
> + */
> +#define LPC32XX_UART_ENABLED_CLOCKS(n)		(((n) >> 16) & 0x7F)
> +#define LPC32XX_UART_ENABLED_CLOCK(n, u)	(((n) >> (16 + (u))) & 0x1)
> +#define LPC32XX_UART_ENABLED_CLKS_ANY		_BIT(14)
> +#define LPC32XX_UART_CLKMODE_OFF		0x0
> +#define LPC32XX_UART_CLKMODE_ON			0x1
> +#define LPC32XX_UART_CLKMODE_AUTO		0x2
> +#define LPC32XX_UART_CLKMODE_MASK(u)		(0x3 << ((((u) - 3) * 2) + 4))
> +#define LPC32XX_UART_CLKMODE_LOAD(m, u)		((m) << ((((u) - 3) * 2) + 4))
> +
> +/*
> + * GPIO Module Register offsets
> + */
> +#define _GPREG(x)				_REG(LPC32XX_GPIO_BASE + (x))
> +#define LPC32XX_GPIO_P_MUX_SET			_GPREG(0x100)
> +#define LPC32XX_GPIO_P_MUX_CLR			_GPREG(0x104)
> +#define LPC32XX_GPIO_P_MUX_STATE		_GPREG(0x108)
> +#define LPC32XX_GPIO_P3_MUX_SET			_GPREG(0x110)
> +#define LPC32XX_GPIO_P3_MUX_CLR			_GPREG(0x114)
> +#define LPC32XX_GPIO_P3_MUX_STATE		_GPREG(0x118)
> +#define LPC32XX_GPIO_P0_MUX_SET			_GPREG(0x120)
> +#define LPC32XX_GPIO_P0_MUX_CLR			_GPREG(0x124)
> +#define LPC32XX_GPIO_P0_MUX_STATE		_GPREG(0x128)
> +#define LPC32XX_GPIO_P1_MUX_SET			_GPREG(0x130)
> +#define LPC32XX_GPIO_P1_MUX_CLR			_GPREG(0x134)
> +#define LPC32XX_GPIO_P1_MUX_STATE		_GPREG(0x138)
> +
> +#endif
> diff --git a/arch/arm/mach-lpc32xx/include/mach/system.h b/arch/arm/mach-lpc32xx/include/mach/system.h
> new file mode 100644
> index 0000000..df3b0de
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/system.h
> @@ -0,0 +1,52 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/system.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __ASM_ARCH_SYSTEM_H
> +#define __ASM_ARCH_SYSTEM_H
> +
> +static void arch_idle(void)
> +{
> +	cpu_do_idle();
> +}
> +
> +static inline void arch_reset(char mode, const char *cmd)
> +{
> +	extern void lpc32xx_watchdog_reset(void);
> +
> +	switch (mode) {
> +	case 's':
> +	case 'h':
> +		printk(KERN_CRIT "RESET: Rebooting system\n");
> +
> +		/* Disable interrupts */
> +		local_irq_disable();
> +
> +		lpc32xx_watchdog_reset();
> +		break;
> +
> +	default:
> +		/* Do nothing */
> +		break;
> +	}
> +
> +	/* Wait for watchdog to reset system */
> +	while (1)
> +		;
> +}
> +
> +#endif
> diff --git a/arch/arm/mach-lpc32xx/include/mach/timex.h b/arch/arm/mach-lpc32xx/include/mach/timex.h
> new file mode 100644
> index 0000000..1b2a20f
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/timex.h
> @@ -0,0 +1,29 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/timex.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __ASM_ARCH_TIMEX_H
> +#define __ASM_ARCH_TIMEX_H
> +
> +/*
> + * Rate in Hz of the main system oscillator. This value should match
> + * the value 'MAIN_OSC_FREQ' in platform.h
> + */
> +#define CLOCK_TICK_RATE	13000000
> +
> +#endif
> +
> diff --git a/arch/arm/mach-lpc32xx/include/mach/uncompress.h b/arch/arm/mach-lpc32xx/include/mach/uncompress.h
> new file mode 100644
> index 0000000..7effa54
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/uncompress.h
> @@ -0,0 +1,63 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/uncompress.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __ASM_ARM_ARCH_UNCOMPRESS_H
> +#define __ASM_ARM_ARCH_UNCOMPRESS_H
> +
> +#include <linux/io.h>
> +
> +#include <mach/platform.h>
> +
> +/*
> + * Uncompress output is hardcoded to standard UART 5
> + */
> +
> +#define UART_FIFO_CTL_TX_RESET	(1 << 2)
> +#define UART_STATUS_TX_MT	(1 << 6)
> +
> +#define LPC32XX_UART_DLLFIFO_O	0x00
> +#define LPC32XX_UART_IIRFCR_O	0x08
> +#define LPC32XX_UART_LSR_O	0x14
> +
> +#define LPC32XX_SUART_DATA	(*(volatile unsigned long *)\
> +				(LPC32XX_UART5_BASE + LPC32XX_UART_DLLFIFO_O))
> +#define LPC32XX_SUART_STATUS	(*(volatile unsigned long *)\
> +				(LPC32XX_UART5_BASE + LPC32XX_UART_LSR_O))
> +#define LPC32XX_SUART_FIFOCTRL	(*(volatile unsigned long *)\
> +				(LPC32XX_UART5_BASE + LPC32XX_UART_IIRFCR_O))
> +
> +static inline void putc(int ch)
> +{
> +	/* Wait for transmit FIFO to empty */
> +	while ((LPC32XX_SUART_STATUS & UART_STATUS_TX_MT) == 0)
> +		;
> +
> +	LPC32XX_SUART_DATA = (u32) ch;
> +}
Why do you use volatile here and not __raw_readl/writel as in the other
files?

> +
> +static inline void flush(void)
> +{
> +	LPC32XX_SUART_FIFOCTRL |= UART_FIFO_CTL_TX_RESET;
> +}
> +
> +/* NULL functions; we don't presently need them */
> +#define arch_decomp_setup()
> +#define arch_decomp_wdog()
> +
> +#endif
> +
trailing newline

> diff --git a/arch/arm/mach-lpc32xx/include/mach/vmalloc.h b/arch/arm/mach-lpc32xx/include/mach/vmalloc.h
> new file mode 100644
> index 0000000..d1d936c
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/vmalloc.h
> @@ -0,0 +1,24 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/vmalloc.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __ASM_ARCH_VMALLOC_H
> +#define __ASM_ARCH_VMALLOC_H
> +
> +#define VMALLOC_END	0xF0000000
> +
> +#endif
> -- 
> 1.6.6

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

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

* [PATCH 02/14] ARM: LPC32XX: Debug and IRQ macros
  2010-02-09  0:11 ` [PATCH 02/14] ARM: LPC32XX: Debug and IRQ macros wellsk40 at gmail.com
@ 2010-02-09  9:45   ` Uwe Kleine-König
  0 siblings, 0 replies; 44+ messages in thread
From: Uwe Kleine-König @ 2010-02-09  9:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 08, 2010 at 04:11:23PM -0800, wellsk40 at gmail.com wrote:
> From: Kevin Wells <wellsk40@gmail.com>
> 
> Debug (printascii) and IRQ handler macros for the LPC32XX
> architecture
> 
> Signed-off-by: Kevin Wells <wellsk40@gmail.com>
> ---
>  arch/arm/mach-lpc32xx/include/mach/debug-macro.S |   54 ++++++++++++++++++++++
>  arch/arm/mach-lpc32xx/include/mach/entry-macro.S |   47 +++++++++++++++++++
>  2 files changed, 101 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-lpc32xx/include/mach/debug-macro.S b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
> new file mode 100644
> index 0000000..cd62e2f
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/debug-macro.S
> @@ -0,0 +1,54 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/debug-macro.S
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <mach/hardware.h>
> +#include <mach/platform.h>
> +
> +#define LPC32XX_UART_DLL_FIFO_OFS	0x00
> +#define LPC32XX_UART_LSR_OFS		0x14
> +
> +/*
> + * Debug output is hardcoded to standard UART 5
> +*/
> +
> +	.macro	addruart,rx
> +	mrc	p15, 0, \rx, c1, c0
> +	tst	\rx, #1				@ MMU enabled?
> +	ldr	\rx, =LPC32XX_UART5_BASE	@ physical
> +	beq	1003f
> +	ldr	\rx, =IO_ADDRESS(LPC32XX_UART5_BASE) @ virtual
> +1003:
You can do this without a branch:

	mrc	p15, 0, \rx, c1, c0
	tst	\rx, #1				@ MMU enabled?
	ldreq	\rx, =LPC32XX_UART5_BASE	@ physical
	ldrne	\rx, =IO_ADDRESS(LPC32XX_UART5_BASE) @ virtual

Maybe expose LPC32XX_UART5_BASE a bit more by a separate #define?  e.g.:

	#define LPC32XX_DEBUG_UART_BASE LPC32XX_UART5_BASE

	...
	ldreq	\rx, =LPC32XX_DEBUG_UART_BASE
	ldrne	\rx, =IO_ADDRESS(LPC32XX_DEBUG_UART_BASE)


> +	.endm
> +
> +	.macro	senduart,rd,rx
> +	str	\rd, [\rx, #LPC32XX_UART_DLL_FIFO_OFS]
> +	.endm
> +
> +	.macro	busyuart,rd,rx
> +1002:
> +	ldr	\rd, [\rx, #LPC32XX_UART_LSR_OFS]
> +	tst	\rd, #(1 << 6)
> +	beq	1002b
> +	.endm
> +
> +	.macro	waituart,rd,rx
> +1001:
> +	ldr	\rd, [\rx, #LPC32XX_UART_LSR_OFS]
> +	tst	\rd, #(1 << 5)
> +	beq	1001b
> +	.endm
> diff --git a/arch/arm/mach-lpc32xx/include/mach/entry-macro.S b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
> new file mode 100644
> index 0000000..870227c
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/include/mach/entry-macro.S
> @@ -0,0 +1,47 @@
> +/*
> + * arch/arm/mach-lpc32xx/include/mach/entry-macro.S
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <mach/hardware.h>
> +#include <mach/platform.h>
> +
> +#define LPC32XX_INTC_MASKED_STATUS_OFS	0x8
> +
> +	.macro	disable_fiq
> +	.endm
> +
> +	.macro  get_irqnr_preamble, base, tmp
> +	ldr	\base, =IO_ADDRESS(LPC32XX_MIC_BASE)
> +	.endm
> +
> +	.macro  arch_ret_to_user, tmp1, tmp2
> +	.endm
> +
> +/*
> + * Return IRQ number in irqnr. Also return processor Z flag status in CPSR
> + * as set if an interrupt is pending.
> + */
> +	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
> +	ldr	\irqstat, [\base, #LPC32XX_INTC_MASKED_STATUS_OFS]
> +	clz	\irqnr, \irqstat
> +	rsb	\irqnr, \irqnr, #31
> +	teq	\irqstat, #0
> +	.endm
> +
> +	.macro	irq_prio_table
> +	.endm
> +
trailing newline

Best regards
Uwe

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

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

* [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
  2010-02-09  9:31   ` Uwe Kleine-König
@ 2010-02-09  9:52     ` Uwe Kleine-König
  2010-02-09  9:59     ` Russell King - ARM Linux
  2010-02-09 19:17     ` Kevin Wells
  2 siblings, 0 replies; 44+ messages in thread
From: Uwe Kleine-König @ 2010-02-09  9:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

while replying to to patch 02, I noticed yet another thing.

On Tue, Feb 09, 2010 at 10:31:29AM +0100, Uwe Kleine-K?nig wrote:
> > +/*
> > + * Start of virtual addresses for IO devices
> > + */
> > +#define IO_BASE		0xF0000000
> > +
> > +/*
> > + * This macro relies on fact that for all HW i/o addresses bits 20-23 are 0
> > + */
> > +#define IO_ADDRESS(x)	(((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) |\
> > +			 IO_BASE)
> > +
> > +#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
> Is this cast to unsigned long needed?  AFAIK IO_ADDRESS(x) has
> type unsigned for x in { 0x0 ... 0xffffffff } (provided that int uses a
> 32 bit 2s-complement representation).  If unsigned long is really
> needed, maybe put it into the IO_ADDRESS macro?
> 
> > ...
> > +#define _REG(x)					(void __iomem *)(io_p2v(x))

_REG gets (void __iomem *) twice.

Why not simply do:

	#define io_p2v(x)	(((((x) & 0xff000000) >> 4) | ((x) & 0xfffff)) | IO_BASE)

	#define _REG(x)		(void __iomem *)(io_p2v(x))

and get rid of IO_ADDRESS completely?  BTW, AFAIK IO_BASE isn't a needed
name, so it should have the LPC32XX_ prefix, too.

Best regards
Uwe

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

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

* [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
  2010-02-09  9:31   ` Uwe Kleine-König
  2010-02-09  9:52     ` Uwe Kleine-König
@ 2010-02-09  9:59     ` Russell King - ARM Linux
  2010-02-09 16:52         ` Uwe Kleine-König
  2010-02-09 19:17     ` Kevin Wells
  2 siblings, 1 reply; 44+ messages in thread
From: Russell King - ARM Linux @ 2010-02-09  9:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 09, 2010 at 10:31:29AM +0100, Uwe Kleine-K?nig wrote:
> > +#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
> Is this cast to unsigned long needed?  AFAIK IO_ADDRESS(x) has
> type unsigned for x in { 0x0 ... 0xffffffff } (provided that int uses a
> 32 bit 2s-complement representation).  If unsigned long is really
> needed, maybe put it into the IO_ADDRESS macro?

int -> void __iomem * = sparse warning
unsigned long -> void __iomem * = no sparse warning

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

* [PATCH 03/14] ARM: LPC32XX: Clock driver
  2010-02-09  0:11 ` [PATCH 03/14] ARM: LPC32XX: Clock driver wellsk40 at gmail.com
@ 2010-02-09 10:39   ` Uwe Kleine-König
  2010-02-09 19:18     ` Kevin Wells
  2010-02-19  0:42     ` Kevin Wells
  0 siblings, 2 replies; 44+ messages in thread
From: Uwe Kleine-König @ 2010-02-09 10:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 08, 2010 at 04:11:24PM -0800, wellsk40 at gmail.com wrote:
> From: Kevin Wells <wellsk40@gmail.com>
> 
> Clock driver for the LPC32XX architecture
> 
> Signed-off-by: Kevin Wells <wellsk40@gmail.com>
> ---
>  arch/arm/mach-lpc32xx/clock.c | 1078 +++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-lpc32xx/clock.h |   37 ++
>  2 files changed, 1115 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-lpc32xx/clock.c b/arch/arm/mach-lpc32xx/clock.c
> new file mode 100644
> index 0000000..4f0b882
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/clock.c
> @@ -0,0 +1,1078 @@
> +/*
> + * arch/arm/mach-lpc32xx/clock.c
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +/*
> + * LPC32xx clock mamagement driver overview
s/mamagement/management/

> + *
> + * The LPC32XX contains a number of high level system clocks that can be
> + * generated from different sources. These system clocks are used to
> + * generate the CPU and bus rates and the individual peripheral clocks in
> + * the system. When Linux is started by the boot loader, the system
> + * clocks are already running. Stopping a system clock during normal
> + * Linux operation should never be attempted, as peripherals that require
> + * those clocks will quit working (ie, DRAM).
> + *
> + * The LPC32xx high level clock tree looks as follows. Clocks marked with
> + * an asterisk are always on and cannot be disabled. Clocks marked with
> + * an ampersand can only be disabled in CPU suspend mode. Clocks marked
> + * with a carot are always on if it is the selected clock for the SYSCLK
s/carot/caret/

> + * source. The clock that isn't used for SYSCLK can be enabled and
> + * disabled normally.
> + *                               32KHz oscillator*
> + *                               /      |      \
> + *                             RTC*   PLL397^ TOUCH
> + *                                     /
> + *               Main oscillator^     /
> + *                   |        \      /
> + *                   |         SYSCLK&
> + *                   |            \
> + *                   |             \
> + *                USB_PLL       HCLK_PLL&
> + *                   |           |    |
> + *            USB host/device  PCLK&  |
> + *                               |    |
> + *                             Peripherals
> + *
> + * The CPU and chip bus rates are derived from the HCLK PLL, which can
> + * generate various clock rates up to 266MHz and beyond. The internal bus
> + * rates (PCLK and HCLK) are generated from dividers based on the HCLK
> + * PLL rate. HCLK can be a ratio of 1:1, 1:2, or 1:4 or HCLK PLL rate,
> + * while PCLK can be 1:1 to 1:32 of HCLK PLL rate. Most peripherals high
> + * level clocks are based on either HCLK or PCLK, but have their own
> + * dividers as part of the IP itself. Because of this, the system clock
> + * rates should not be changed.
> + *
> + * The HCLK PLL is clocked from SYSCLK, which can be derived from the
> + * main oscillator or PLL397. PLL397 generates a rate that is 397 times
> + * the 32KHz oscillator rate. The main oscillator runs at the selected
> + * oscillator/crystal rate on the mosc_in pin of the LPC32xx. This rate
> + * is normally 13MHz, but depends on the selection of external crystals
> + * or oscillators. If USB operation is required, the main oscillator must
> + * be used in the system.
> + *
> + * Switching SYSCLK between sources during normal Linux operation is not
> + * supported. SYSCLK is preset in the bootloader. Because of the
> + * complexities of clock management during clock frequency changes,
> + * there are some limitations to the clock driver explained below:
> + * - The PLL397 and main oscillator can be enabled and disabled by the
> + *   clk_enable() and clk_disable() functions unless SYSCLK is based
> + *   on that clock. This allows the other oscillator that isn't driving
> + *   the HCLK PLL to be used as another system clock that can be routed
> + *   to an external pin.
> + * - The muxed SYSCLK input and HCLK_PLL rate cannot be changed with
> + *   this driver.
> + * - HCLK and PCLK rates cannot be changed as part of this driver.
> + * - Most peripherals have their own dividers are part of the peripheral
> + *   block. Changing SYSCLK, HCLK PLL, HCLK, or PCLK sources or rates
> + *   will also impact the individual peripheral rates.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/errno.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/clk.h>
> +#include <linux/amba/bus.h>
> +#include <linux/amba/clcd.h>
> +
> +#include <mach/hardware.h>
> +#include <asm/clkdev.h>
> +#include <mach/clkdev.h>
> +#include <mach/platform.h>
> +#include "clock.h"
> +#include "common.h"
> +
> +static struct clk clk_armpll;
> +static struct clk clk_usbpll;
> +static struct mutex clkm_lock;
static DEFINE_MUTEX(clkm_lock);

then you don't need to mutex_init below.

> +
> +/*
> + * Post divider values for PLLs based on selected register value
> + */
> +const u32 pll_postdivs[4] = {1, 2, 4, 8};
make this static, too?

> +
> +static u32 local_return_parent_rate(struct clk *clk)
> +{
> +	/*
> +	 * If a clock has a rate of 0, then it inherits it's parent
> +	 * clock rate
> +	 */
> +	if (clk->rate == 0)
> +		return local_return_parent_rate(clk->parent);
> +
> +	return clk->rate;
> +}
> +
> +/* 32KHz clock has a fixed rate and is not stoppable */
> +static struct clk osc_32KHz = {
> +	.rate		= LPC32XX_CLOCK_OSC_FREQ,
> +	.get_rate	= &local_return_parent_rate,
The address operator -----^ isn't needed and commonly omitted.

> +};
> +
> +static int local_pll397_enable(struct clk *clk, int enable)
> +{
> +	u32 reg;
> +	unsigned long timeout = 1 + msecs_to_jiffies(10);
> +
> +	reg = __raw_readl(LPC32XX_CLKPWR_PLL397_CTRL);
> +
> +	if (enable == 0) 	{
> +		reg |= LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS;
> +		__raw_writel(reg, LPC32XX_CLKPWR_PLL397_CTRL);
> +		clk->rate = 0;
I think you don't need to zero rate here.  get_rate isn't guaranteed to
return the right value if the clock is off, but you don't need to
"destroy" the right value on purpose.

> +	} else {
> +		/* Enable PLL397 */
> +		reg &= ~LPC32XX_CLKPWR_SYSCTRL_PLL397_DIS;
> +		__raw_writel(reg, LPC32XX_CLKPWR_PLL397_CTRL);
> +		clk->rate = LPC32XX_CLOCK_OSC_FREQ * 397;
> +
> +		/* Wait for PLL397 lock */
> +		while (((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) &
> +			LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0) &&
> +			(timeout > jiffies))
> +			cpu_relax();
> +
> +		if ((__raw_readl(LPC32XX_CLKPWR_PLL397_CTRL) &
> +			LPC32XX_CLKPWR_SYSCTRL_PLL397_STS) == 0)
> +			return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +static int local_oscmain_enable(struct clk *clk, int enable)
> +{
> +	u32 reg;
> +	unsigned long timeout = 1 + msecs_to_jiffies(10);
> +
> +	reg = __raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL);
> +
> +	if (enable == 0) {
> +		reg |= LPC32XX_CLKPWR_MOSC_DISABLE;
> +		__raw_writel(reg, LPC32XX_CLKPWR_MAIN_OSC_CTRL);
> +		clk->rate = 0;
> +	} else {
> +		/* Enable main oscillator */
> +		reg &= ~LPC32XX_CLKPWR_MOSC_DISABLE;
> +		__raw_writel(reg, LPC32XX_CLKPWR_MAIN_OSC_CTRL);
> +		clk->rate = LPC32XX_MAIN_OSC_FREQ;
> +
> +		/* Wait for main oscillator to start */
> +		while (((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) &
> +			LPC32XX_CLKPWR_MOSC_DISABLE) != 0) &&
> +			(timeout > jiffies))
> +			cpu_relax();
> +
> +		if ((__raw_readl(LPC32XX_CLKPWR_MAIN_OSC_CTRL) &
> +			LPC32XX_CLKPWR_MOSC_DISABLE) != 0)
> +			return -ENODEV;
> +	}
> +
> +	return 0;
> +}
> +
> +static struct clk osc_pll397 = {
> +	.parent		= &osc_32KHz,
> +	.enable		= &local_pll397_enable,
> +	.rate		= LPC32XX_CLOCK_OSC_FREQ * 397,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk osc_main = {
> +	.enable		= &local_oscmain_enable,
> +	.rate		= LPC32XX_MAIN_OSC_FREQ,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_sys;
> +
> +/*
> + * Setup the HCLK PLL with a PLL structure
> + */
> +static u32 local_clk_pll_setup(struct clk_pll_setup *PllSetup)
> +{
> +	u32 tv, tmp = 0;
> +
> +	if (PllSetup->analog_on != 0)
> +		tmp |= LPC32XX_CLKPWR_HCLKPLL_POWER_UP;
> +	if (PllSetup->cco_bypass_b15 != 0)
> +		tmp |= LPC32XX_CLKPWR_HCLKPLL_CCO_BYPASS;
> +	if (PllSetup->direct_output_b14 != 0)
> +		tmp |= LPC32XX_CLKPWR_HCLKPLL_POSTDIV_BYPASS;
> +	if (PllSetup->fdbk_div_ctrl_b13 != 0)
> +		tmp |= LPC32XX_CLKPWR_HCLKPLL_FDBK_SEL_FCLK;
> +
> +	switch (PllSetup->pll_p) {
> +	case 1:
> +		tv = 0;
> +		break;
> +
> +	case 2:
> +		tv = 1;
> +		break;
> +
> +	case 4:
> +		tv = 2;
> +		break;
> +
> +	case 8:
> +		tv = 3;
> +		break;
> +
> +	default:
> +		return 0;
> +	}
I don't know the hardware details here, but maybe using ffs and
is_power_of_2 is more efficient?

> +	tmp |= LPC32XX_CLKPWR_HCLKPLL_POSTDIV_2POW(tv);
> +	tmp |= LPC32XX_CLKPWR_HCLKPLL_PREDIV_PLUS1(PllSetup->pll_n - 1);
> +	tmp |= LPC32XX_CLKPWR_HCLKPLL_PLLM(PllSetup->pll_m - 1);
> +
> +	return tmp;
> +}
> +
> +/*
> + * Update the ARM core PLL frequency rate variable from the actual PLL setting
> + */
> +static void local_update_armpll_rate(void)
> +{
> +	u32 clkin, pllreg;
> +
> +	clkin = clk_armpll.parent->rate;
> +	pllreg = __raw_readl(LPC32XX_CLKPWR_HCLKPLL_CTRL) & 0x1FFFF;
> +
> +	clk_armpll.rate = clk_get_pllrate_from_reg(clkin, pllreg);
> +}
> +
> +/*
> + * Find a PLL configuration for the selected input frequency
> + */
> +static u32 local_clk_find_pll_cfg(u32 pllin_freq, u32 target_freq,
> +	struct clk_pll_setup *pllsetup)
> +{
> +	u32 ifreq, freqtol, m, n, p, fclkout;
> +
> +	/* Determine frequency tolerance limits */
> +	freqtol = target_freq / 250;
> +	ifreq = pllin_freq;
> +
> +	/* Is direct bypass mode possible? */
> +	if (abs(pllin_freq - target_freq) <= freqtol) {
> +		pllsetup->analog_on = 0;
> +		pllsetup->cco_bypass_b15 = 1;
> +		pllsetup->direct_output_b14 = 1;
> +		pllsetup->fdbk_div_ctrl_b13 = 1;
> +		pllsetup->pll_p = pll_postdivs[0];
> +		pllsetup->pll_n = 1;
> +		pllsetup->pll_m = 1;
> +		return clk_check_pll_setup(ifreq, pllsetup);
> +	} else if (target_freq <= ifreq) {
> +		pllsetup->analog_on = 0;
> +		pllsetup->cco_bypass_b15 = 1;
> +		pllsetup->direct_output_b14 = 0;
> +		pllsetup->fdbk_div_ctrl_b13 = 1;
> +		pllsetup->pll_n = 1;
> +		pllsetup->pll_m = 1;
> +		for (p = 0; p <= 3; p++) {
> +			pllsetup->pll_p = pll_postdivs[p];
> +			fclkout = clk_check_pll_setup(ifreq, pllsetup);
> +			if (abs(target_freq - fclkout) <= freqtol)
> +				return fclkout;
> +		}
> +	}
> +
> +	/* Is direct mode possible? */
> +	pllsetup->analog_on = 1;
> +	pllsetup->cco_bypass_b15 = 0;
> +	pllsetup->direct_output_b14 = 1;
> +	pllsetup->fdbk_div_ctrl_b13 = 0;
> +	pllsetup->pll_p = pll_postdivs[0];
> +	for (m = 1; m <= 256; m++) {
> +		for (n = 1; n <= 4; n++) {
> +			/* Compute output frequency for this value */
> +			pllsetup->pll_n = n;
> +			pllsetup->pll_m = m;
> +			fclkout = clk_check_pll_setup(ifreq,
> +				pllsetup);
> +			if (abs(target_freq - fclkout) <=
> +				freqtol)
> +				return fclkout;
> +		}
> +	}
> +
> +	/* Is integer mode possible? */
> +	pllsetup->analog_on = 1;
> +	pllsetup->cco_bypass_b15 = 0;
> +	pllsetup->direct_output_b14 = 0;
> +	pllsetup->fdbk_div_ctrl_b13 = 1;
> +	for (m = 1; m <= 256; m++) {
> +		for (n = 1; n <= 4; n++) {
> +			for (p = 0; p < 4; p++) {
> +				/* Compute output frequency */
> +				pllsetup->pll_p = pll_postdivs[p];
> +				pllsetup->pll_n = n;
> +				pllsetup->pll_m = m;
> +				fclkout = clk_check_pll_setup(
> +					ifreq, pllsetup);
> +				if (abs(target_freq - fclkout) <= freqtol)
> +					return fclkout;
> +			}
> +		}
> +	}
> +
> +	/* Try non-integer mode */
> +	pllsetup->analog_on = 1;
> +	pllsetup->cco_bypass_b15 = 0;
> +	pllsetup->direct_output_b14 = 0;
> +	pllsetup->fdbk_div_ctrl_b13 = 0;
> +	for (m = 1; m <= 256; m++) {
> +		for (n = 1; n <= 4; n++) {
> +			for (p = 0; p < 4; p++) {
> +				/* Compute output frequency */
> +				pllsetup->pll_p = pll_postdivs[p];
> +				pllsetup->pll_n = n;
> +				pllsetup->pll_m = m;
> +				fclkout = clk_check_pll_setup(
> +					ifreq, pllsetup);
> +				if (abs(target_freq - fclkout) <= freqtol)
> +					return fclkout;
> +			}
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static struct clk clk_armpll = {
> +	.parent		= &clk_sys,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +/*
> + * Update the USB PLL frequency rate variable from the actual PLL setting
> + */
> +static void local_update_usbpll_rate(void)
> +{
> +	u32 clkin, pllreg;
> +
> +	clkin = clk_usbpll.get_rate(&clk_usbpll);
> +	pllreg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL) & 0x1FFFF;
> +
> +	if ((pllreg & LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP) == 0)
> +		clk_usbpll.rate = 0;
> +	else
> +		clk_usbpll.rate = clk_get_pllrate_from_reg(clkin,
> +			pllreg);
> +}
> +
> +/*
> + * Setup the USB PLL with a PLL structure
> + */
> +static u32 local_clk_usbpll_setup(struct clk_pll_setup *pHCLKPllSetup)
> +{
> +	u32 reg, tmp = local_clk_pll_setup(pHCLKPllSetup);
> +
> +	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL) & ~0x1FFFF;
> +	reg |= tmp;
> +	__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
> +
> +	return clk_check_pll_setup(clk_usbpll.parent->rate,
> +		pHCLKPllSetup);
> +}
> +
> +static int local_usbpll_enable(struct clk *clk, int enable)
> +{
> +	u32 reg;
> +	int ret = -ENODEV;
> +	unsigned long timeout = 1 + msecs_to_jiffies(10);
> +
> +	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
> +
> +	if (enable == 0) {
> +		reg &= ~(LPC32XX_CLKPWR_USBCTRL_CLK_EN1 |
> +			LPC32XX_CLKPWR_USBCTRL_CLK_EN2);
> +		__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
> +	} else if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_PWRUP) {
> +		reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1;
> +		__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
> +
> +		/* Wait for PLL lock */
> +		while ((timeout > jiffies) & (ret == -ENODEV)) {
> +			reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
> +			if (reg & LPC32XX_CLKPWR_USBCTRL_PLL_STS)
> +				ret = 0;
> +		}
> +
> +		if (ret == 0) {
> +			reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2;
> +			__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +static int local_usbpll_set_rate(struct clk *clk, u32 rate)
> +{
> +	u32 clkin, reg, usbdiv;
> +	struct clk_pll_setup pllsetup;
> +
> +	/*
> +	 * Unlike other clocks, this clock has a KHz input rate, so bump
> +	 * it up to work with the PLL function
> +	 */
> +	rate = rate * 1000;
> +
> +	local_usbpll_enable(clk, 0);
> +
> +	if (rate == 0)
> +		return 0;
> +
> +	clkin = clk->parent->rate;
> +	usbdiv = __raw_readl(LPC32XX_CLKPWR_USBCLK_PDIV) + 1;
> +	clkin = clkin / usbdiv;
> +
> +	/* Try to find a good rate setup */
> +	if (local_clk_find_pll_cfg(clkin, rate, &pllsetup) == 0)
> +		return -EINVAL;
> +
> +	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
> +	reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN1;
> +	__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
> +
> +	pllsetup.analog_on = 1;
> +	local_clk_usbpll_setup(&pllsetup);
> +
> +	clk->rate = clk_check_pll_setup(clkin, &pllsetup);
> +
> +	reg = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
> +	reg |= LPC32XX_CLKPWR_USBCTRL_CLK_EN2;
> +	__raw_writel(reg, LPC32XX_CLKPWR_USB_CTRL);
> +
> +	return 0;
> +}
> +
> +static struct clk clk_usbpll = {
> +	.parent		= &osc_main,
> +	.set_rate	= &local_usbpll_set_rate,
> +	.enable		= &local_usbpll_enable,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static u32 clk_get_hclk_div(void)
> +{
> +	static const u32 hclkdivs[4] = {1, 2, 4, 4};
> +	return hclkdivs[LPC32XX_CLKPWR_HCLKDIV_DIV_2POW(
> +		__raw_readl(LPC32XX_CLKPWR_HCLK_DIV))];
> +}
> +
> +static struct clk clk_hclk = {
> +	.parent		= &clk_armpll,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_pclk = {
> +	.parent		= &clk_armpll,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static int local_onoff_enable(struct clk *clk, int enable)
> +{
> +	u32 tmp;
> +
> +	tmp = __raw_readl(clk->enable_reg);
> +
> +	if (enable == 0)
> +		tmp &= ~clk->enable_mask;
> +	else
> +		tmp |= clk->enable_mask;
> +
> +	__raw_writel(tmp, clk->enable_reg);
> +
> +	return 0;
> +}
> +
> +/* Peripheral clock sources */
> +static struct clk clk_timer0 = {
> +	.parent		= &clk_pclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
> +	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +static struct clk clk_timer1 = {
> +	.parent		= &clk_pclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
> +	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +static struct clk clk_timer2 = {
> +	.parent		= &clk_pclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
> +	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER2_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +static struct clk clk_timer3 = {
> +	.parent		= &clk_pclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1,
> +	.enable_mask	= LPC32XX_CLKPWR_TMRPWMCLK_TIMER3_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +static struct clk clk_wdt = {
> +	.parent		= &clk_pclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_TIMER_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_PWMCLK_WDOG_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +static struct clk clk_vfp9 = {
> +	.parent		= &clk_pclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_DEBUG_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_VFP_CLOCK_ENABLE_BIT,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +static struct clk clk_dma = {
> +	.parent		= &clk_hclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_DMA_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_uart3 = {
> +	.parent		= &clk_pclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART3_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_uart4 = {
> +	.parent		= &clk_pclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART4_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_uart5 = {
> +	.parent		= &clk_pclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART5_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_uart6 = {
> +	.parent		= &clk_pclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_UART_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_UARTCLKCTRL_UART6_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_i2c0 = {
> +	.parent		= &clk_hclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_I2C_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_I2CCLK_I2C1CLK_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_i2c1 = {
> +	.parent		= &clk_hclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_I2C_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_I2CCLK_I2C2CLK_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_i2c2 = {
> +	.parent		= &clk_pclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= io_p2v(LPC32XX_USB_BASE + 0xFF4),
> +	.enable_mask	= 0x4,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_ssp0 = {
> +	.parent		= &clk_hclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_SSP_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_ssp1 = {
> +	.parent		= &clk_hclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_SSP_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_SSPCTRL_SSPCLK1_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_kscan = {
> +	.parent		= &osc_32KHz,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_KEY_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_KEYCLKCTRL_CLK_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_nand = {
> +	.parent		= &clk_hclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_NAND_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_i2s0 = {
> +	.parent		= &clk_hclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_I2S_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_I2SCTRL_I2SCLK0_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_i2s1 = {
> +	.parent		= &clk_hclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_I2S_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_net = {
> +	.parent		= &clk_hclk,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_MACCLK_CTRL,
> +	.enable_mask	= (LPC32XX_CLKPWR_MACCTRL_DMACLK_EN |
> +		LPC32XX_CLKPWR_MACCTRL_MMIOCLK_EN |
> +		LPC32XX_CLKPWR_MACCTRL_HRCCLK_EN),
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_rtc = {
> +	.parent		= &osc_32KHz,
> +	.rate		= 1, /* 1 Hz */
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static struct clk clk_usbd = {
> +	.parent		= &clk_usbpll,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_USB_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_USBCTRL_HCLK_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static int tsc_onoff_enable(struct clk *clk, int enable)
> +{
> +	u32 tmp;
> +
> +	/* Make sure 32KHz clock is the selected clock */
> +	tmp = __raw_readl(LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
> +	tmp &= ~LPC32XX_CLKPWR_ADCCTRL1_PCLK_SEL;
> +	__raw_writel(tmp, LPC32XX_CLKPWR_ADC_CLK_CTRL_1);
> +
> +	if (enable == 0)
> +		__raw_writel(0, clk->enable_reg);
> +	else
> +		__raw_writel(clk->enable_mask, clk->enable_reg);
> +
> +	return 0;
> +}
> +
> +static struct clk clk_tsc = {
> +	.parent		= &osc_32KHz,
> +	.enable		= &tsc_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_ADC_CLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_ADC32CLKCTRL_CLK_EN,
> +	.get_rate	= &local_return_parent_rate,
> +};
> +
> +static int mmc_onoff_enable(struct clk *clk, int enable)
> +{
> +	u32 tmp;
> +
> +	tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) &
> +		~(LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
> +		LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(15));
> +
> +	/* If rate is 0, disable clock */
> +	if (enable != 0)
> +		tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
> +			LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(1);
> +
> +	__raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
> +
> +	return 0;
> +}
> +
> +static u32 mmc_get_rate(struct clk *clk)
> +{
> +	u32 div, tmp, rate;
> +
> +	div = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
> +	tmp = div & LPC32XX_CLKPWR_MSCARD_SDCARD_EN;
> +
> +	if (!tmp)
> +		return 0;
> +
> +	/* Get the parent clock rate */
> +	rate = clk->parent->get_rate(clk->parent);
> +
> +	/* Get the LCD controller clock divider value */
> +	div = div & 0xF;
> +
> +	if (!div)
> +		return 0;
> +
> +	tmp = rate / div;
> +
> +	return tmp;
> +}
> +
> +static int mmc_set_rate(struct clk *clk, u32 rate)
> +{
> +	if (rate == 0)
> +		mmc_onoff_enable(clk, 0);
> +	else
> +		mmc_onoff_enable(clk, 1);
> +
> +	return 0;
> +}
> +
> +static struct clk clk_mmc = {
> +	.parent		= &clk_armpll,
> +	.set_rate	= &mmc_set_rate,
> +	.get_rate	= &mmc_get_rate,
> +	.enable		= &mmc_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_MS_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_MSCARD_SDCARD_EN,
> +};
> +
> +static u32 clcd_get_rate(struct clk *clk)
> +{
> +	u32 tmp, div, rate;
> +
> +	tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) &
> +		LPC32XX_CLKPWR_LCDCTRL_CLK_EN;
> +
> +	if (!tmp)
> +		return 0;
> +
> +	rate = clk->parent->get_rate(clk->parent);
> +	tmp = __raw_readl(io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2));
> +
> +	/* Only supports internal clocking */
> +	if (tmp & TIM2_BCD)
> +		return rate;
> +
> +	div = (tmp & 0x1F) | ((tmp & 0xF8) >> 22);
> +	tmp = rate / (2 + div);
> +
> +	return tmp;
> +}
> +
> +static int clcd_set_rate(struct clk *clk, u32 rate)
> +{
> +	u32 tmp, prate, div;
> +
> +	tmp = __raw_readl(io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2));
> +	prate = clk->parent->get_rate(clk->parent);
> +
> +	if (rate == prate) {
> +		tmp |= TIM2_BCD;
> +		local_onoff_enable(clk, 1);
> +	} else {
> +		/* Find closest divider */
> +		div = prate / rate;
> +		if (div == 1)
> +			div = 0;
> +		else
> +			div -= 2;
> +
> +		tmp &= ~(0xF800001F);
> +		tmp &= ~TIM2_BCD;
> +		tmp |= (div & 0x1F);
> +		tmp |= (((div >> 5) & 0x1F) << 27);
> +		__raw_writel(tmp, io_p2v(LPC32XX_LCD_BASE + CLCD_TIM2));
> +		local_onoff_enable(clk, 1);
> +	}
> +
> +	return 0;
> +}
> +
> +static struct clk clk_lcd = {
> +	.parent		= &clk_hclk,
> +	.set_rate	= &clcd_set_rate,
> +	.get_rate	= &clcd_get_rate,
> +	.enable		= &local_onoff_enable,
> +	.enable_reg	= LPC32XX_CLKPWR_LCDCLK_CTRL,
> +	.enable_mask	= LPC32XX_CLKPWR_LCDCTRL_CLK_EN,
> +};
> +
> +static inline void clk_lock(void)
> +{
> +	mutex_lock(&clkm_lock);
> +}
> +
> +static inline void clk_unlock(void)
> +{
> +	mutex_unlock(&clkm_lock);
> +}
> +
> +static void local_clk_disable(struct clk *clk)
> +{
> +	/* Don't attempt to disable clock if it has no users */
WARN_ON(clk->usecount <= 0)?

> +	if (clk->usecount > 0) {
> +		clk->usecount--;
> +
> +		/* Only disable clock when it has no more users */
> +		if ((clk->usecount == 0) && (clk->enable))
> +			clk->enable(clk, 0);
> +
> +		/* Check parent clocks, they may need to be disabled too */
> +		if (clk->parent)
> +			local_clk_disable(clk->parent);
> +	}
> +}
> +
> +static int local_clk_enable(struct clk *clk)
> +{
> +	int ret = 0;
> +
> +	if (clk->usecount == 0) {
> +		/* Enable parent clocks first */
> +		if (clk->parent)
> +			ret = local_clk_enable(clk->parent);
> +
> +		/* Enable clock on first use */
> +		if ((ret == 0) && (clk->enable)) {
> +			ret = clk->enable(clk, 1);
> +			clk->usecount++;
> +		}
> +
> +		/* Back out use counters if enable fails */
> +		if (ret < 0)
> +			local_clk_disable(clk);
if enable failed there is no need to disable, is it?

And I think the reference counting is broken.

After

	clk_enable(aclk);
	clk_enable(aclk);
	clk_disable(aclk);

aclk is disabled because usecount isn't increased if it is already >0!?


> +	}
> +
> +	return ret;
> +}
> +
> +/*
> + * clk_enable - inform the system when the clock source should be running.
> + */
> +int clk_enable(struct clk *clk)
> +{
> +	int ret;
> +
> +	clk_lock();
> +	ret = local_clk_enable(clk);
> +	clk_unlock();
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(clk_enable);
> +
> +/*
> + * clk_disable - inform the system when the clock source is no longer required
> + */
> +void clk_disable(struct clk *clk)
> +{
> +	clk_lock();
> +	local_clk_disable(clk);
> +	clk_unlock();
> +}
> +EXPORT_SYMBOL(clk_disable);
> +
> +/*
> + * clk_get_rate - obtain the current clock rate (in Hz) for a clock source
> + */
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> +	unsigned long rate;
> +
> +	clk_lock();
> +	rate = (clk->get_rate)(clk);
> +	clk_unlock();
> +
> +	return rate;
> +}
> +EXPORT_SYMBOL(clk_get_rate);
> +
> +/*
> + * clk_set_rate - set the clock rate for a clock source
> + */
> +int clk_set_rate(struct clk *clk, unsigned long rate)
> +{
> +	int ret = -EINVAL;
> +
> +	/*
> +	 * Most system clocks can only be enabled or disabled, with
> +	 * the actual rate set as part of the peripheral dividers
> +	 * instead of high level clock control
> +	 */
> +	if (clk->set_rate) {
> +		clk_lock();
> +		ret = (clk->set_rate)(clk, rate);
> +		clk_unlock();
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(clk_set_rate);
> +
> +/*
> + * clk_round_rate - adjust a rate to the exact rate a clock can provide
> + */
> +long clk_round_rate(struct clk *clk, unsigned long rate)
> +{
> +	int ret;
> +
> +	/* Use set_rate to try to adjust the rate if it supports it */
> +	ret = clk_set_rate(clk, rate);
> +	if (ret < 0)
> +		return ret;
> +
> +	return clk->rate;
> +}
> +EXPORT_SYMBOL(clk_round_rate);
> +
> +/*
> + * clk_set_parent - set the parent clock source for this clock
> + */
> +int clk_set_parent(struct clk *clk, struct clk *parent)
> +{
> +	/* Clock re-parenting is not supported */
> +	return -EINVAL;
> +}
> +EXPORT_SYMBOL(clk_set_parent);
> +
> +/*
> + * clk_get_parent - get the parent clock source for this clock
> + */
> +struct clk *clk_get_parent(struct clk *clk)
> +{
> +	return clk->parent;
> +}
> +EXPORT_SYMBOL(clk_get_parent);
> +
> +#define _REGISTER_CLOCK(d, n, c) \
> +	{ \
> +		.dev_id = (d), \
> +		.con_id = (n), \
> +		.clk = &(c), \
> +	},
> +
> +static struct clk_lookup lookups[] = {
> +	_REGISTER_CLOCK(NULL, "osc_32KHz", osc_32KHz)
> +	_REGISTER_CLOCK(NULL, "osc_pll397", osc_pll397)
> +	_REGISTER_CLOCK(NULL, "osc_main", osc_main)
> +	_REGISTER_CLOCK(NULL, "sys_ck", clk_sys)
> +	_REGISTER_CLOCK(NULL, "arm_pll_ck", clk_armpll)
> +	_REGISTER_CLOCK(NULL, "ck_pll5", clk_usbpll)
> +	_REGISTER_CLOCK(NULL, "hclk_ck", clk_hclk)
> +	_REGISTER_CLOCK(NULL, "pclk_ck", clk_pclk)
> +	_REGISTER_CLOCK(NULL, "timer0_ck", clk_timer0)
> +	_REGISTER_CLOCK(NULL, "timer1_ck", clk_timer1)
> +	_REGISTER_CLOCK(NULL, "timer2_ck", clk_timer2)
> +	_REGISTER_CLOCK(NULL, "timer3_ck", clk_timer3)
> +	_REGISTER_CLOCK(NULL, "vfp9_ck", clk_vfp9)
> +	_REGISTER_CLOCK(NULL, "clk_dmac", clk_dma)
> +	_REGISTER_CLOCK("pnx4008-watchdog", NULL, clk_wdt)
> +	_REGISTER_CLOCK(NULL, "uart3_ck", clk_uart3)
> +	_REGISTER_CLOCK(NULL, "uart4_ck", clk_uart4)
> +	_REGISTER_CLOCK(NULL, "uart5_ck", clk_uart5)
> +	_REGISTER_CLOCK(NULL, "uart6_ck", clk_uart6)
> +	_REGISTER_CLOCK("pnx-i2c.0", NULL, clk_i2c0)
> +	_REGISTER_CLOCK("pnx-i2c.1", NULL, clk_i2c1)
> +	_REGISTER_CLOCK("pnx-i2c.2", NULL, clk_i2c2)
> +	_REGISTER_CLOCK("dev:ssp0", NULL, clk_ssp0)
> +	_REGISTER_CLOCK("dev:ssp1", NULL, clk_ssp1)
> +	_REGISTER_CLOCK("lpc32xx_keys.0", NULL, clk_kscan)
> +	_REGISTER_CLOCK("lpc32xx-nand.0", "nand_ck", clk_nand)
> +	_REGISTER_CLOCK("tbd", "i2s0_ck", clk_i2s0)
> +	_REGISTER_CLOCK("tbd", "i2s1_ck", clk_i2s1)
> +	_REGISTER_CLOCK("lpc32xx-ts", NULL, clk_tsc)
> +	_REGISTER_CLOCK("dev:mmc0", "MCLK", clk_mmc)
> +	_REGISTER_CLOCK("lpc-net.0", NULL, clk_net)
> +	_REGISTER_CLOCK("dev:clcd", NULL, clk_lcd)
> +	_REGISTER_CLOCK("lpc32xx_udc", "ck_usbd", clk_usbd)
> +	_REGISTER_CLOCK("lpc32xx_rtc", NULL, clk_rtc)
> +};
> +
> +static int __init clk_init(void)
> +{
> +	int i;
> +
> +	mutex_init(&clkm_lock);
> +
> +	for (i = 0; i < ARRAY_SIZE(lookups); i++)
> +		clkdev_add(&lookups[i]);
> +
> +	/*
> +	 * Setup muxed SYSCLK for HCLK PLL base -this selects the
> +	 * parent clock used for the ARM PLL and is used to derive
> +	 * the many system clock rates in the device.
> +	 */
> +	if (clk_is_sysclk_mainosc() != 0)
> +		clk_sys.parent = &osc_main;
> +	else
> +		clk_sys.parent = &osc_pll397;
> +
> +	clk_sys.rate = clk_sys.parent->rate;
> +
> +	/* Compute the current ARM PLL and USB PLL frequencies */
> +	local_update_armpll_rate();
> +	local_update_usbpll_rate();
> +
> +	/* Compute HCLK and PCLK bus rates */
> +	clk_hclk.rate = clk_hclk.parent->rate / clk_get_hclk_div();
> +	clk_pclk.rate = clk_pclk.parent->rate / clk_get_pclk_div();
> +
> +	/*
> +	 * Enable system clocks - this step is somewhat formal, as the
> +	 * clocks are already running, but it does get the clock data
> +	 * inline with the actual system state. Never disable these
> +	 * clocks as they will only stop if the system is going to sleep.
> +	 * In that case, the chip/system power management functions will
> +	 * handle clock gating.
> +	 */
> +	clk_enable(&clk_hclk);
> +	clk_enable(&clk_pclk);
> +
> +	/*
> +	 * Timers 0 and 1 were enabled and are being used by the high
> +	 * resolution tick function prior to this driver being initialized.
> +	 * Tag them now as used.
> +	 */
> +	clk_enable(&clk_timer0);
> +	clk_enable(&clk_timer1);
> +
> +	return 0;
> +}
> +core_initcall(clk_init);
> +
> diff --git a/arch/arm/mach-lpc32xx/clock.h b/arch/arm/mach-lpc32xx/clock.h
> new file mode 100644
> index 0000000..97789b9
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/clock.h
> @@ -0,0 +1,37 @@
> +/*
> + * arch/arm/mach-lpc32xx/clock.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __LPC32XX_CLOCK_H
> +#define __LPC32XX_CLOCK_H
> +
> +struct clk {
> +	struct list_head node;
> +	struct clk *parent;
> +	u32 rate;
> +	s8 usecount;
why is usecount a signed value?  You don't save anything here with using
an 8bit quantity because of padding.  So you can use u32 with no cost.

> +
> +	int (*set_rate) (struct clk *, u32);
> +	int (*enable) (struct clk *clk, int);
> +	u32 (*get_rate) (struct clk *clk);
> +
> +	/* Register address and bit mask for simple clocks */
> +	void __iomem *enable_reg;
> +	u32 enable_mask;
> +};
> +
> +#endif

Best regards
Uwe

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

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

* [PATCH 04/14] ARM: LPC32XX: GPIO, timer, and IRQ drivers
  2010-02-09  0:11 ` [PATCH 04/14] ARM: LPC32XX: GPIO, timer, and IRQ drivers wellsk40 at gmail.com
@ 2010-02-09 10:58   ` Uwe Kleine-König
  0 siblings, 0 replies; 44+ messages in thread
From: Uwe Kleine-König @ 2010-02-09 10:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 08, 2010 at 04:11:25PM -0800, wellsk40 at gmail.com wrote:
> From: Kevin Wells <wellsk40@gmail.com>
> 
> Common drivers for the LPC32XX used on all platforms
> 
> Signed-off-by: Kevin Wells <wellsk40@gmail.com>
> ---
>  arch/arm/mach-lpc32xx/gpiolib.c |  458 +++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-lpc32xx/irq.c     |  438 +++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-lpc32xx/timer.c   |  182 ++++++++++++++++
>  3 files changed, 1078 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-lpc32xx/gpiolib.c b/arch/arm/mach-lpc32xx/gpiolib.c
> new file mode 100644
> index 0000000..202cd82
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/gpiolib.c
> @@ -0,0 +1,458 @@
> +/*
> + * arch/arm/mach-lpc32xx/gpiolib.c
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/errno.h>
> +#include <linux/gpio.h>
> +
> +#include <mach/hardware.h>
> +#include <mach/platform.h>
> +#include "common.h"
> +
> +#define LPC32XX_GPIO_P3_INP_STATE		_GPREG(0x000)
> +#define LPC32XX_GPIO_P3_OUTP_SET		_GPREG(0x004)
> +#define LPC32XX_GPIO_P3_OUTP_CLR		_GPREG(0x008)
> +#define LPC32XX_GPIO_P3_OUTP_STATE		_GPREG(0x00C)
> +#define LPC32XX_GPIO_P2_DIR_SET			_GPREG(0x010)
> +#define LPC32XX_GPIO_P2_DIR_CLR			_GPREG(0x014)
> +#define LPC32XX_GPIO_P2_DIR_STATE		_GPREG(0x018)
> +#define LPC32XX_GPIO_P2_INP_STATE		_GPREG(0x01C)
> +#define LPC32XX_GPIO_P2_OUTP_SET		_GPREG(0x020)
> +#define LPC32XX_GPIO_P2_OUTP_CLR		_GPREG(0x024)
> +#define LPC32XX_GPIO_P2_MUX_SET			_GPREG(0x028)
> +#define LPC32XX_GPIO_P2_MUX_CLR			_GPREG(0x02C)
> +#define LPC32XX_GPIO_P2_MUX_STATE		_GPREG(0x030)
> +#define LPC32XX_GPIO_P0_INP_STATE		_GPREG(0x040)
> +#define LPC32XX_GPIO_P0_OUTP_SET		_GPREG(0x044)
> +#define LPC32XX_GPIO_P0_OUTP_CLR		_GPREG(0x048)
> +#define LPC32XX_GPIO_P0_OUTP_STATE		_GPREG(0x04C)
> +#define LPC32XX_GPIO_P0_DIR_SET			_GPREG(0x050)
> +#define LPC32XX_GPIO_P0_DIR_CLR			_GPREG(0x054)
> +#define LPC32XX_GPIO_P0_DIR_STATE		_GPREG(0x058)
> +#define LPC32XX_GPIO_P1_INP_STATE		_GPREG(0x060)
> +#define LPC32XX_GPIO_P1_OUTP_SET		_GPREG(0x064)
> +#define LPC32XX_GPIO_P1_OUTP_CLR		_GPREG(0x068)
> +#define LPC32XX_GPIO_P1_OUTP_STATE		_GPREG(0x06C)
> +#define LPC32XX_GPIO_P1_DIR_SET			_GPREG(0x070)
> +#define LPC32XX_GPIO_P1_DIR_CLR			_GPREG(0x074)
> +#define LPC32XX_GPIO_P1_DIR_STATE		_GPREG(0x078)
> +
> +#define GPIO012_PIN_TO_BIT(x)			(1 << (x))
> +#define GPIO3_PIN_TO_BIT(x)			(1 << ((x) + 25))
> +#define GPO3_PIN_TO_BIT(x)			(1 << (x))
> +#define GPIO012_PIN_IN_SEL(x, y)		(((x) >> (y)) & 1)
> +#define GPIO3_PIN_IN_SEL(x, y)			(((x) >> (10 + (y))) & 1)
> +#define GPIO3_PIN5_IN_SEL(x)			(((x) >> 24) & 1)
> +#define GPI3_PIN_IN_SEL(x, y)			(((x) >> (y)) & 1)
> +
> +struct gpio_regs {
> +	void __iomem *inp_state;
> +	void __iomem *outp_set;
> +	void __iomem *outp_clr;
> +	void __iomem *dir_set;
> +	void __iomem *dir_clr;
> +};
> +
> +/*
> + * GPIO names
> + */
> +static const char *gpio_p0_names[LPC32XX_GPIO_P0_MAX] = {
> +	"p0.0", "p0.1", "p0.2", "p0.3",
> +	"p0.4", "p0.5", "p0.6", "p0.7"
> +};
> +
> +static const char *gpio_p1_names[LPC32XX_GPIO_P1_MAX] = {
> +	"p1.0", "p1.1", "p1.2", "p1.3",
> +	"p1.4", "p1.5", "p1.6", "p1.7",
> +	"p1.8", "p1.9", "p1.10", "p1.11",
> +	"p1.12", "p1.13", "p1.14", "p1.15",
> +	"p1.16", "p1.17", "p1.18", "p1.19",
> +	"p1.20", "p1.21", "p1.22", "p1.23",
> +};
> +
> +static const char *gpio_p2_names[LPC32XX_GPIO_P2_MAX] = {
> +	"p2.0", "p2.1", "p2.2", "p2.3",
> +	"p2.4", "p2.5", "p2.6", "p2.7",
> +	"p2.8", "p2.9", "p2.10", "p2.11",
> +	"p2.12"
> +};
> +
> +static const char *gpio_p3_names[LPC32XX_GPIO_P3_MAX] = {
> +	"gpi000", "gpio01", "gpio02", "gpio03",
> +	"gpio04", "gpio05"
> +};
> +
> +static const char *gpi_p3_names[LPC32XX_GPI_P3_MAX] = {
> +	"gpi00", "gpi01", "gpi02", "gpi03",
> +	"gpi04", "gpi05", "gpi06", "gpi07",
> +	"gpi08", "gpi09",  NULL,    NULL,
> +	 NULL,    NULL,    NULL,   "gpi15",
> +	"gpi16", "gpi17", "gpi18", "gpi19",
> +	"gpi20", "gpi21", "gpi22", "gpi23",
> +	"gpi24", "gpi25", "gpi26", "gpi27"
> +};
> +
> +static const char *gpo_p3_names[LPC32XX_GPO_P3_MAX] = {
> +	"gpo00", "gpo01", "gpo02", "gpo03",
> +	"gpo04", "gpo05", "gpo06", "gpo07",
> +	"gpo08", "gpo09", "gpo10", "gpo11",
> +	"gpo12", "gpo13", "gpo14", "gpo15",
> +	"gpo16", "gpo17", "gpo18", "gpo19",
> +	"gpo20", "gpo21", "gpo22", "gpo23"
> +};
> +
> +static struct gpio_regs gpio_grp_regs_p0 = {
> +	.inp_state	= LPC32XX_GPIO_P0_INP_STATE,
> +	.outp_set	= LPC32XX_GPIO_P0_OUTP_SET,
> +	.outp_clr	= LPC32XX_GPIO_P0_OUTP_CLR,
> +	.dir_set	= LPC32XX_GPIO_P0_DIR_SET,
> +	.dir_clr	= LPC32XX_GPIO_P0_DIR_CLR,
> +};
> +
> +static struct gpio_regs gpio_grp_regs_p1 = {
> +	.inp_state	= LPC32XX_GPIO_P1_INP_STATE,
> +	.outp_set	= LPC32XX_GPIO_P1_OUTP_SET,
> +	.outp_clr	= LPC32XX_GPIO_P1_OUTP_CLR,
> +	.dir_set	= LPC32XX_GPIO_P1_DIR_SET,
> +	.dir_clr	= LPC32XX_GPIO_P1_DIR_CLR,
> +};
> +
> +static struct gpio_regs gpio_grp_regs_p2 = {
> +	.inp_state	= LPC32XX_GPIO_P2_INP_STATE,
> +	.outp_set	= LPC32XX_GPIO_P2_OUTP_SET,
> +	.outp_clr	= LPC32XX_GPIO_P2_OUTP_CLR,
> +	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
> +	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
> +};
> +
> +static struct gpio_regs gpio_grp_regs_p3 = {
> +	.inp_state	= LPC32XX_GPIO_P3_INP_STATE,
> +	.outp_set	= LPC32XX_GPIO_P3_OUTP_SET,
> +	.outp_clr	= LPC32XX_GPIO_P3_OUTP_CLR,
> +	.dir_set	= LPC32XX_GPIO_P2_DIR_SET,
> +	.dir_clr	= LPC32XX_GPIO_P2_DIR_CLR,
> +};
> +
> +struct lpc32xx_gpio_chip {
> +	struct gpio_chip	chip;
> +	struct gpio_regs	*gpio_grp;
> +};
> +
> +static inline struct lpc32xx_gpio_chip *to_lpc32xx_gpio(
> +	struct gpio_chip *gpc)
> +{
> +	return container_of(gpc, struct lpc32xx_gpio_chip, chip);
> +}
> +
> +static void __set_gpio_dir_p012(struct lpc32xx_gpio_chip *group,
> +	unsigned pin, int input)
> +{
> +	if (input)
> +		__raw_writel(GPIO012_PIN_TO_BIT(pin),
> +			group->gpio_grp->dir_clr);
> +	else
> +		__raw_writel(GPIO012_PIN_TO_BIT(pin),
> +			group->gpio_grp->dir_set);
> +}
> +
> +static void __set_gpio_dir_p3(struct lpc32xx_gpio_chip *group,
> +	unsigned pin, int input)
> +{
> +	u32 u;
> +
> +	/* P3 GPIO pins are offset in the register to pin mapping */
> +	u =  GPIO3_PIN_TO_BIT(pin);
here ------^ is a superflous space.

> +
> +	if (input)
> +		__raw_writel(u, group->gpio_grp->dir_clr);
> +	else
> +		__raw_writel(u, group->gpio_grp->dir_set);
> +}
> +
> +static void __set_gpio_level_p012(struct lpc32xx_gpio_chip *group,
> +	unsigned pin, int high)
> +{
> +	if (high)
> +		__raw_writel(GPIO012_PIN_TO_BIT(pin),
> +			group->gpio_grp->outp_set);
> +	else
> +		__raw_writel(GPIO012_PIN_TO_BIT(pin),
> +			group->gpio_grp->outp_clr);
> +}
> +
> +static void __set_gpio_level_p3(struct lpc32xx_gpio_chip *group,
> +	unsigned pin, int high)
> +{
> +	u32 u;
> +
> +	/* P3 GPIO pins are offset in the register to pin mapping */
> +	u = GPIO3_PIN_TO_BIT(pin);

	u32 u = ...
?

> +
> +	if (high)
> +		__raw_writel(u, group->gpio_grp->outp_set);
> +	else
> +		__raw_writel(u, group->gpio_grp->outp_clr);
> +}
> +
> +static void __set_gpo_level_p3(struct lpc32xx_gpio_chip *group,
> +	unsigned pin, int high)
> +{
> +	if (high)
> +		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_set);
> +	else
> +		__raw_writel(GPO3_PIN_TO_BIT(pin), group->gpio_grp->outp_clr);
> +}
> +
> +static int __get_gpio_state_p012(struct lpc32xx_gpio_chip *group,
> +	unsigned pin)
> +{
> +	return GPIO012_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state),
> +		pin);
> +}
> +
> +static int __get_gpio_state_p3(struct lpc32xx_gpio_chip *group,
> +	unsigned pin)
> +{
> +	int state;
> +
> +	state = __raw_readl(group->gpio_grp->inp_state);
> +
> +	/*
> +	 * P3 GPIO pin input mapping is not contiguous, GPIOP3-0..4 is mapped
> +	 * to bits 10..14, while GPIOP3-5 is mapped to bit 24.
> +	 */
> +	if (pin == 5)
> +		state = GPIO3_PIN5_IN_SEL(state);
> +	else
> +		state = GPIO3_PIN_IN_SEL(state, pin);
I would hide that in GPIO3_PIN_IN_SEL, e.g.


	#define GPIO3_PIN_IN_SHIFT(pin)		(pin == 5 ? 24 : 10 + (pin))
	#define GPIO3_PIN_IN_SEL(state, pin)	(((state) >> GPIO3_PIN_IN_SHIFT(pin)) & 1)

> +
> +	return state;
> +}
> +
> +static int __get_gpi_state_p3(struct lpc32xx_gpio_chip *group,
> +	unsigned pin)
> +{
> +	return GPI3_PIN_IN_SEL(__raw_readl(group->gpio_grp->inp_state), pin);
> +}
> +
> +/*
> + * GENERIC_GPIO primitives.
> + */
> +static int lpc32xx_gpio_dir_input_p012(struct gpio_chip *chip,
> +	unsigned pin)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +
> +	__set_gpio_dir_p012(group, pin, 1);
> +
> +	return 0;
> +}
> +
> +static int lpc32xx_gpio_dir_input_p3(struct gpio_chip *chip,
> +	unsigned pin)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +
> +	__set_gpio_dir_p3(group, pin, 1);
> +
> +	return 0;
> +}
> +
> +static int lpc32xx_gpio_dir_in_always(struct gpio_chip *chip,
> +	unsigned pin)
> +{
> +	return 0;
> +}
> +
> +static int lpc32xx_gpio_get_value_p012(struct gpio_chip *chip, unsigned pin)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +
> +	return __get_gpio_state_p012(group, pin);
> +}
> +
> +static int lpc32xx_gpio_get_value_p3(struct gpio_chip *chip, unsigned pin)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +
> +	return __get_gpio_state_p3(group, pin);
> +}
> +
> +static int lpc32xx_gpi_get_value(struct gpio_chip *chip, unsigned pin)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +
> +	return __get_gpi_state_p3(group, pin);
> +}
> +
> +static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
> +	int value)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +
> +	__set_gpio_dir_p012(group, pin, 0);
> +
> +	return 0;
> +}
> +
> +static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
> +	int value)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +
> +	__set_gpio_dir_p3(group, pin, 0);
> +
> +	return 0;
> +}
> +
> +static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
> +	int value)
> +{
> +	return 0;
> +}
> +
> +static void lpc32xx_gpio_set_value_p012(struct gpio_chip *chip, unsigned pin,
> +	int value)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +
> +	__set_gpio_level_p012(group, pin, value);
> +}
> +
> +static void lpc32xx_gpio_set_value_p3(struct gpio_chip *chip, unsigned pin,
> +	int value)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +
> +	__set_gpio_level_p3(group, pin, value);
> +}
> +
> +static void lpc32xx_gpo_set_value(struct gpio_chip *chip, unsigned pin,
> +	int value)
> +{
> +	struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
> +
> +	__set_gpo_level_p3(group, pin, value);
> +}
> +
> +static int lpc32xx_gpio_request(struct gpio_chip *chip, unsigned pin)
> +{
> +	if (pin < chip->ngpio)
> +		return 0;
> +
> +	return -EINVAL;
> +}
> +
> +static struct lpc32xx_gpio_chip lpc32xx_gpiochip[] = {
> +	{
> +		.chip = {
> +			.label			= "gpio_p0",
> +			.direction_input	= lpc32xx_gpio_dir_input_p012,
> +			.get			= lpc32xx_gpio_get_value_p012,
> +			.direction_output	= lpc32xx_gpio_dir_output_p012,
> +			.set			= lpc32xx_gpio_set_value_p012,
> +			.request		= lpc32xx_gpio_request,
> +			.base			= LPC32XX_GPIO_P0_GRP,
> +			.ngpio			= LPC32XX_GPIO_P0_MAX,
> +			.names			= gpio_p0_names,
> +			.can_sleep		= 0,
> +		},
> +		.gpio_grp = &gpio_grp_regs_p0,
> +	},
> +	{
> +		.chip = {
> +			.label			= "gpio_p1",
> +			.direction_input	= lpc32xx_gpio_dir_input_p012,
> +			.get			= lpc32xx_gpio_get_value_p012,
> +			.direction_output	= lpc32xx_gpio_dir_output_p012,
> +			.set			= lpc32xx_gpio_set_value_p012,
> +			.request		= lpc32xx_gpio_request,
> +			.base			= LPC32XX_GPIO_P1_GRP,
> +			.ngpio			= LPC32XX_GPIO_P1_MAX,
> +			.names			= gpio_p1_names,
> +			.can_sleep		= 0,
> +		},
> +		.gpio_grp = &gpio_grp_regs_p1,
> +	},
> +	{
> +		.chip = {
> +			.label			= "gpio_p2",
> +			.direction_input	= lpc32xx_gpio_dir_input_p012,
> +			.get			= lpc32xx_gpio_get_value_p012,
> +			.direction_output	= lpc32xx_gpio_dir_output_p012,
> +			.set			= lpc32xx_gpio_set_value_p012,
> +			.request		= lpc32xx_gpio_request,
> +			.base			= LPC32XX_GPIO_P2_GRP,
> +			.ngpio			= LPC32XX_GPIO_P2_MAX,
> +			.names			= gpio_p2_names,
> +			.can_sleep		= 0,
> +		},
> +		.gpio_grp = &gpio_grp_regs_p2,
> +	},
> +	{
> +		.chip = {
> +			.label			= "gpio_p3",
> +			.direction_input	= lpc32xx_gpio_dir_input_p3,
> +			.get			= lpc32xx_gpio_get_value_p3,
> +			.direction_output	= lpc32xx_gpio_dir_output_p3,
> +			.set			= lpc32xx_gpio_set_value_p3,
> +			.request		= lpc32xx_gpio_request,
> +			.base			= LPC32XX_GPIO_P3_GRP,
> +			.ngpio			= LPC32XX_GPIO_P3_MAX,
> +			.names			= gpio_p3_names,
> +			.can_sleep		= 0,
> +		},
> +		.gpio_grp = &gpio_grp_regs_p3,
> +	},
> +	{
> +		.chip = {
> +			.label			= "gpi_p3",
> +			.direction_input	= lpc32xx_gpio_dir_in_always,
> +			.get			= lpc32xx_gpi_get_value,
> +			.request		= lpc32xx_gpio_request,
> +			.base			= LPC32XX_GPI_P3_GRP,
> +			.ngpio			= LPC32XX_GPI_P3_MAX,
> +			.names			= gpi_p3_names,
> +			.can_sleep		= 0,
> +		},
> +		.gpio_grp = &gpio_grp_regs_p3,
> +	},
> +	{
> +		.chip = {
> +			.label			= "gpo_p3",
> +			.direction_output	= lpc32xx_gpio_dir_out_always,
> +			.set			= lpc32xx_gpo_set_value,
> +			.request		= lpc32xx_gpio_request,
> +			.base			= LPC32XX_GPO_P3_GRP,
> +			.ngpio			= LPC32XX_GPO_P3_MAX,
> +			.names			= gpo_p3_names,
> +			.can_sleep		= 0,
> +		},
> +		.gpio_grp = &gpio_grp_regs_p3,
> +	},
> +};
> +
> +void __init lpc32xx_gpio_init(void)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(lpc32xx_gpiochip); i++)
> +		gpiochip_add(&lpc32xx_gpiochip[i].chip);
> +}
> diff --git a/arch/arm/mach-lpc32xx/irq.c b/arch/arm/mach-lpc32xx/irq.c
> new file mode 100644
> index 0000000..18c3caf
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/irq.c
> @@ -0,0 +1,438 @@
> +/*
> + * arch/arm/mach-lpc32xx/irq.c
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/types.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +
> +#include <mach/irqs.h>
> +#include <mach/hardware.h>
> +#include <mach/platform.h>
> +#include "common.h"
> +
> +/*
> + * Default value representing the Activation polarity of all internal
> + * interrupt sources
> + */
> +#define MIC_APR_DEFAULT		0x3FF0EFE0
> +#define SIC1_APR_DEFAULT	0xFBD27186
> +#define SIC2_APR_DEFAULT	0x801810C0
> +
> +/*
> + * Default value representing the Activation Type of all internal
> + * interrupt sources. All are level sensitive.
> + */
> +#define MIC_ATR_DEFAULT		0x00000000
> +#define SIC1_ATR_DEFAULT	0x00026000
> +#define SIC2_ATR_DEFAULT	0x00000000
> +
> +struct lpc32xx_event_group_regs {
> +	void __iomem *enab_reg;
> +	void __iomem *edge_reg;
> +	void __iomem *maskstat_reg;
> +	void __iomem *rawstat_reg;
> +};
> +
> +static const struct lpc32xx_event_group_regs lpc32xx_event_int_regs = {
> +	.enab_reg = LPC32XX_CLKPWR_INT_ER,
> +	.edge_reg = LPC32XX_CLKPWR_INT_AP,
> +	.maskstat_reg = LPC32XX_CLKPWR_INT_SR,
> +	.rawstat_reg = LPC32XX_CLKPWR_INT_RS,
> +};
> +
> +static const struct lpc32xx_event_group_regs lpc32xx_event_pin_regs = {
> +	.enab_reg = LPC32XX_CLKPWR_PIN_ER,
> +	.edge_reg = LPC32XX_CLKPWR_PIN_AP,
> +	.maskstat_reg = LPC32XX_CLKPWR_PIN_SR,
> +	.rawstat_reg = LPC32XX_CLKPWR_PIN_RS,
> +};
> +
> +struct lpc32xx_event_info {
> +	const struct lpc32xx_event_group_regs *event_group;
> +	u32 mask;
> +};
> +
> +/*
> + * Maps an IRQ number to and event mask and register
> + */
> +static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
> +	[IRQ_LPC32XX_GPI_08] = {
> +		.event_group = &lpc32xx_event_pin_regs,
> +		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_08_BIT,
> +	},
> +	[IRQ_LPC32XX_GPI_09] = {
> +		.event_group = &lpc32xx_event_pin_regs,
> +		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_09_BIT,
> +	},
> +	[IRQ_LPC32XX_GPI_19] = {
> +		.event_group = &lpc32xx_event_pin_regs,
> +		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_19_BIT,
> +	},
> +	[IRQ_LPC32XX_GPI_07] = {
> +		.event_group = &lpc32xx_event_pin_regs,
> +		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_07_BIT,
> +	},
> +	[IRQ_LPC32XX_GPI_00] = {
> +		.event_group = &lpc32xx_event_pin_regs,
> +		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_00_BIT,
> +	},
> +	[IRQ_LPC32XX_GPI_01] = {
> +		.event_group = &lpc32xx_event_pin_regs,
> +		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_01_BIT,
> +	},
> +	[IRQ_LPC32XX_GPI_02] = {
> +		.event_group = &lpc32xx_event_pin_regs,
> +		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_02_BIT,
> +	},
> +	[IRQ_LPC32XX_GPI_03] = {
> +		.event_group = &lpc32xx_event_pin_regs,
> +		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_03_BIT,
> +	},
> +	[IRQ_LPC32XX_GPI_04] = {
> +		.event_group = &lpc32xx_event_pin_regs,
> +		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_04_BIT,
> +	},
> +	[IRQ_LPC32XX_GPI_05] = {
> +		.event_group = &lpc32xx_event_pin_regs,
> +		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_05_BIT,
> +	},
> +	[IRQ_LPC32XX_GPI_06] = {
> +		.event_group = &lpc32xx_event_pin_regs,
> +		.mask = LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT,
> +	},
> +	[IRQ_LPC32XX_GPIO_00] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT,
> +	},
> +	[IRQ_LPC32XX_GPIO_01] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_01_BIT,
> +	},
> +	[IRQ_LPC32XX_GPIO_02] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_02_BIT,
> +	},
> +	[IRQ_LPC32XX_GPIO_03] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_03_BIT,
> +	},
> +	[IRQ_LPC32XX_GPIO_04] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_04_BIT,
> +	},
> +	[IRQ_LPC32XX_GPIO_05] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_GPIO_05_BIT,
> +	},
> +	[IRQ_LPC32XX_KEY] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_KEY_BIT,
> +	},
> +	[IRQ_LPC32XX_USB_OTG_ATX] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_USBATXINT_BIT,
> +	},
> +	[IRQ_LPC32XX_USB_HOST] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_USB_BIT,
> +	},
> +	[IRQ_LPC32XX_RTC] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_RTC_BIT,
> +	},
> +	[IRQ_LPC32XX_MSTIMER] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT,
> +	},
> +	[IRQ_LPC32XX_TS_AUX] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_TS_AUX_BIT,
> +	},
> +	[IRQ_LPC32XX_TS_P] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_TS_P_BIT,
> +	},
> +	[IRQ_LPC32XX_TS_IRQ] = {
> +		.event_group = &lpc32xx_event_int_regs,
> +		.mask = LPC32XX_CLKPWR_INTSRC_ADC_BIT,
> +	},
> +};
> +
> +static void get_controller(unsigned int irq, unsigned int *base,
> +	unsigned int *irqbit)
> +{
> +	if (irq < 32) {
> +		*base = LPC32XX_MIC_BASE;
> +		*irqbit = 1 << irq;
> +	} else if (irq < 64) {
> +		*base = LPC32XX_SIC1_BASE;
> +		*irqbit = 1 << (irq - 32);
> +	} else {
> +		*base = LPC32XX_SIC2_BASE;
> +		*irqbit = 1 << (irq - 64);
> +	}
> +}
> +
> +static void lpc32xx_mask_irq(unsigned int irq)
> +{
> +	unsigned int reg, ctrl, mask;
> +
> +	get_controller(irq, &ctrl, &mask);
> +
> +	reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) & ~mask;
> +	__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
> +}
> +
> +static void lpc32xx_unmask_irq(unsigned int irq)
> +{
> +	unsigned int reg, ctrl, mask;
> +
> +	get_controller(irq, &ctrl, &mask);
> +
> +	reg = __raw_readl(LPC32XX_INTC_MASK(ctrl)) | mask;
> +	__raw_writel(reg, LPC32XX_INTC_MASK(ctrl));
> +}
> +
> +static void lpc32xx_ack_irq(unsigned int irq)
> +{
> +	unsigned int ctrl, mask;
> +
> +	get_controller(irq, &ctrl, &mask);
> +
> +	__raw_writel(mask, LPC32XX_INTC_RAW_STAT(ctrl));
> +
> +	/* Also need to clear pending wake event */
> +	if (lpc32xx_events[irq].mask != 0)
> +		__raw_writel(lpc32xx_events[irq].mask,
> +			lpc32xx_events[irq].event_group->rawstat_reg);
> +}
> +
> +static void __lpc32xx_set_irq_type(unsigned int irq, int use_high_level,
> +	int use_edge)
> +{
> +	unsigned int reg, ctrl, mask;
> +
> +	get_controller(irq, &ctrl, &mask);
> +
> +	/* Activation level, high or low */
> +	reg = __raw_readl(LPC32XX_INTC_POLAR(ctrl));
> +	if (use_high_level)
> +		reg |= mask;
> +	else
> +		reg &= ~mask;
> +	__raw_writel(reg, LPC32XX_INTC_POLAR(ctrl));
> +
> +	/* Activation type, edge or level */
> +	reg = __raw_readl(LPC32XX_INTC_ACT_TYPE(ctrl));
> +	if (use_edge) {
> +		reg |= mask;
> +		set_irq_handler(irq, handle_edge_irq);
> +	} else {
> +		reg &= ~mask;
> +		set_irq_handler(irq, handle_level_irq);
> +	}
> +
> +	/* Use same polarity for the wake events */
> +	if (lpc32xx_events[irq].mask != 0) {
> +		reg = __raw_readl(lpc32xx_events[irq].event_group->edge_reg);
> +
> +		if (use_high_level)
> +			reg |= lpc32xx_events[irq].mask;
> +		else
> +			reg &= ~lpc32xx_events[irq].mask;
> +
> +		__raw_writel(reg, lpc32xx_events[irq].event_group->edge_reg);
> +	}
> +}
> +
> +static int lpc32xx_set_irq_type(unsigned int irq, unsigned int type)
> +{
> +	switch (type) {
> +	case IRQ_TYPE_EDGE_RISING:
> +		/* Rising edge sensitive */
> +		__lpc32xx_set_irq_type(irq, 1, 1);
> +		break;
> +
> +	case IRQ_TYPE_EDGE_FALLING:
> +		/* Falling edge sensitive */
> +		__lpc32xx_set_irq_type(irq, 0, 1);
> +		break;
> +
> +	case IRQ_TYPE_LEVEL_LOW:
> +		/* Low level sensitive */
> +		__lpc32xx_set_irq_type(irq, 0, 0);
> +		break;
> +
> +	case IRQ_TYPE_LEVEL_HIGH:
> +		/* High level sensitive */
> +		__lpc32xx_set_irq_type(irq, 1, 0);
> +		break;
> +
> +	/* Other modes are not supported */
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	/* Ok to use the level handler for all types */
> +	set_irq_handler(irq, handle_level_irq);
> +
> +	return 0;
> +}
> +
> +static int lpc32xx_irq_wake(unsigned int irqno, unsigned int state)
> +{
> +	unsigned long eventreg;
> +
> +	if (lpc32xx_events[irqno].mask != 0) {
> +		eventreg = __raw_readl(lpc32xx_events[irqno].
> +			event_group->enab_reg);
> +
> +		if (state)
> +			eventreg |= lpc32xx_events[irqno].mask;
> +		else
> +			eventreg &= ~lpc32xx_events[irqno].mask;
> +
> +		__raw_writel(eventreg,
> +			lpc32xx_events[irqno].event_group->enab_reg);
> +
> +		return 0;
> +	}
> +
> +	/* Clear event */
> +	__raw_writel(lpc32xx_events[irqno].mask,
> +		lpc32xx_events[irqno].event_group->rawstat_reg);
> +
> +	return -ENODEV;
> +}
> +
> +static void __init lpc32xx_set_default_mappings(unsigned int apr,
> +	unsigned int atr, unsigned int offset)
> +{
> +	unsigned int i;
> +
> +	/* Set activation levels for each interrupt */
> +	i = 0;
> +	while (i < 32) {
> +		__lpc32xx_set_irq_type(offset + i, ((apr >> i) & 0x1),
> +			((atr >> i) & 0x1));
> +		i++;
> +	}
> +}
> +
> +static struct irq_chip lpc32xx_irq_chip = {
> +	.ack = lpc32xx_ack_irq,
> +	.mask = lpc32xx_mask_irq,
> +	.unmask = lpc32xx_unmask_irq,
> +	.set_type = lpc32xx_set_irq_type,
> +	.set_wake = lpc32xx_irq_wake
> +};
> +
> +#define SIC1_IRQ(x) ((x) + 32)
> +#define SIC2_IRQ(x) ((x) + 64)
> +
> +static void lpc32xx_sic1_handler(unsigned int irq, struct irq_desc *desc)
> +{
> +	unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC1_BASE));
> +
> +	while (ints != 0) {
> +		int irqno = fls(ints) - 1;
> +
> +		ints &= ~(1 << irqno);
> +
> +		handle_level_irq(SIC1_IRQ(irqno), desc);
> +	}
> +}
> +
> +static void lpc32xx_sic2_handler(unsigned int irq, struct irq_desc *desc)
> +{
> +	unsigned long ints = __raw_readl(LPC32XX_INTC_STAT(LPC32XX_SIC2_BASE));
> +
> +	while (ints != 0) {
> +		int irqno = fls(ints) - 1;
> +
> +		ints &= ~(1 << irqno);
> +
> +		handle_level_irq(SIC2_IRQ(irqno), desc);
This is wrong!  You call handle_level_irq(SIC2_IRQ(irqno)) with the
descriptor of IRQ_LPC32XX_SUB2IRQ.

Better use

	generic_handle_irq(SIC2_IRQ(irqno));

and don't hardcode handle_level_irq here.

> +	}
> +}
> +
> +void __init lpc32xx_init_irq(void)
> +{
> +	unsigned int i;
> +
> +	/* Setup MIC */
> +	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
> +	__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_MIC_BASE));
> +	__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_MIC_BASE));
> +
> +	/* Setup SIC1 */
> +	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
> +	__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC1_BASE));
> +	__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC1_BASE));
> +
> +	/* Setup SIC2 */
> +	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
> +	__raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC2_BASE));
> +	__raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE));
> +
> +	/* Configure supported IRQ's */
> +	for (i = 0; i < NR_IRQS; i++) {
> +		set_irq_chip(i, &lpc32xx_irq_chip);
> +		set_irq_handler(i, handle_level_irq);
> +		set_irq_flags(i, IRQF_VALID);
> +	}
> +
> +	/* Set default mappings */
> +	lpc32xx_set_default_mappings(MIC_APR_DEFAULT, MIC_ATR_DEFAULT, 0);
> +	lpc32xx_set_default_mappings(SIC1_APR_DEFAULT, SIC1_ATR_DEFAULT, 32);
> +	lpc32xx_set_default_mappings(SIC2_APR_DEFAULT, SIC2_ATR_DEFAULT, 64);
> +
> +	/* MIC SUBIRQx interrupts will route handling to the chain handlers */
> +	set_irq_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
> +	set_irq_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
> +
> +	/* mask all interrupts except SUBIRQ */
> +	__raw_writel((1 << IRQ_LPC32XX_SUB1IRQ) | (1 << IRQ_LPC32XX_SUB2IRQ),
> +		LPC32XX_INTC_MASK(LPC32XX_MIC_BASE));
> +	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
> +	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
set_irq_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler) calls
lpc32xx_irq_chip->enable(IRQ_LPC32XX_SUB2IRQ), so first masking all irqs
and only then calling set_irq_chained_handler should do the right thing.

> +
> +	/* Initially disable all wake events */
> +	__raw_writel(0, LPC32XX_CLKPWR_P01_ER);
> +	__raw_writel(0, LPC32XX_CLKPWR_INT_ER);
> +	__raw_writel(0, LPC32XX_CLKPWR_PIN_ER);
> +
> +	/*
> +	 * Default wake activation polarities, all pin sources are low edge
> +	 * triggered
> +	 */
> +	__raw_writel(LPC32XX_CLKPWR_INTSRC_TS_P_BIT |
> +		LPC32XX_CLKPWR_INTSRC_MSTIMER_BIT |
> +		LPC32XX_CLKPWR_INTSRC_RTC_BIT,
> +		LPC32XX_CLKPWR_INT_AP);
> +	__raw_writel(0, LPC32XX_CLKPWR_PIN_AP);
> +
> +	/* Clear latched wake event states */
> +	__raw_writel(__raw_readl(LPC32XX_CLKPWR_PIN_RS),
> +		LPC32XX_CLKPWR_PIN_RS);
> +	__raw_writel(__raw_readl(LPC32XX_CLKPWR_INT_RS),
> +		LPC32XX_CLKPWR_INT_RS);
> +}
> diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c
> new file mode 100644
> index 0000000..630dd4a
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/timer.c
> @@ -0,0 +1,182 @@
> +/*
> + * arch/arm/mach-lpc32xx/timer.c
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * 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>
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/time.h>
> +#include <linux/err.h>
> +#include <linux/clockchips.h>
> +
> +#include <asm/mach/time.h>
> +
> +#include <mach/hardware.h>
> +#include <mach/platform.h>
> +#include "common.h"
> +
> +static cycle_t lpc32xx_clksrc_read(struct clocksource *cs)
> +{
> +	return (cycle_t)__raw_readl(LCP32XX_TIMER_TC(LPC32XX_TIMER1_BASE));
> +}
> +
> +static struct clocksource lpc32xx_clksrc = {
> +	.name	= "lpc32xx_clksrc",
> +	.shift	= 24,
> +	.rating	= 300,
> +	.read	= lpc32xx_clksrc_read,
> +	.mask	= CLOCKSOURCE_MASK(32),
> +	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
> +};
> +
> +static int lpc32xx_clkevt_next_event(unsigned long delta,
> +    struct clock_event_device *dev)
> +{
> +	__raw_writel(LCP32XX_TIMER_CNTR_TCR_RESET,
> +		LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
> +	__raw_writel(delta, LCP32XX_TIMER_PR(LPC32XX_TIMER0_BASE));
> +	__raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
> +		LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
> +
> +	return 0;
> +}
> +
> +static void lpc32xx_clkevt_mode(enum clock_event_mode mode,
> +    struct clock_event_device *dev)
> +{
> +	switch (mode) {
> +	case CLOCK_EVT_MODE_PERIODIC:
> +		WARN_ON(1);
> +		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, LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
> +		break;
> +
> +	case CLOCK_EVT_MODE_UNUSED:
> +	case CLOCK_EVT_MODE_RESUME:
> +		break;
> +	}
> +}
> +
> +static struct clock_event_device lpc32xx_clkevt = {
> +	.name		= "lpc32xx_clkevt",
> +	.features	= CLOCK_EVT_FEAT_ONESHOT,
> +	.shift		= 32,
> +	.rating		= 300,
> +	.set_next_event	= lpc32xx_clkevt_next_event,
> +	.set_mode	= lpc32xx_clkevt_mode,
> +};
> +
> +static irqreturn_t lpc32xx_timer_interrupt(int irq, void *dev_id)
> +{
> +	struct clock_event_device *evt = &lpc32xx_clkevt;
> +
> +	/* Clear match */
> +	__raw_writel(LCP32XX_TIMER_CNTR_MTCH_BIT(0),
> +		LCP32XX_TIMER_IR(LPC32XX_TIMER0_BASE));
> +
> +	evt->event_handler(evt);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static struct irqaction lpc32xx_timer_irq = {
> +	.name		= "LPC32XX Timer Tick",
> +	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
> +	.handler	= lpc32xx_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 lpc32xx_timer_init(void)
> +{
> +	u32 clkrate, pllreg;
> +
> +	/* Enable timer clock */
> +	__raw_writel(LPC32XX_CLKPWR_TMRPWMCLK_TIMER0_EN |
> +		LPC32XX_CLKPWR_TMRPWMCLK_TIMER1_EN,
> +		LPC32XX_CLKPWR_TIMERS_PWMS_CLK_CTRL_1);
> +
> +	/*
> +	 * The clock driver isn't initialized at this point. So determine if
> +	 * the SYSCLK is driven from the PLL397 or main oscillator and then use
> +	 * it to compute the PLL frequency and the PCLK divider to get the base
> +	 * timer rates. This rate is needed to compute the tick rate.
> +	 */
> +	if (clk_is_sysclk_mainosc() != 0)
> +		clkrate = LPC32XX_MAIN_OSC_FREQ;
> +	else
> +		clkrate = 397 * LPC32XX_CLOCK_OSC_FREQ;
> +
> +	/* Get ARM HCLKPLL register and convert it into a frequency */
> +	pllreg = __raw_readl(LPC32XX_CLKPWR_HCLKPLL_CTRL) & 0x1FFFF;
> +	clkrate = clk_get_pllrate_from_reg(clkrate, pllreg);
> +
> +	/* Get PCLK divider and divide ARM PLL clock by it to get timer rate */
> +	clkrate = clkrate / clk_get_pclk_div();
> +
> +	/* Initial timer setup */
> +	__raw_writel(0, LCP32XX_TIMER_TCR(LPC32XX_TIMER0_BASE));
> +	__raw_writel(LCP32XX_TIMER_CNTR_MTCH_BIT(0),
> +		LCP32XX_TIMER_IR(LPC32XX_TIMER0_BASE));
> +	__raw_writel(1, LCP32XX_TIMER_MR0(LPC32XX_TIMER0_BASE));
> +	__raw_writel(LCP32XX_TIMER_CNTR_MCR_MTCH(0) |
> +		LCP32XX_TIMER_CNTR_MCR_STOP(0) |
> +		LCP32XX_TIMER_CNTR_MCR_RESET(0),
> +		LCP32XX_TIMER_MCR(LPC32XX_TIMER0_BASE));
> +
> +	/* Setup tick interrupt */
> +	setup_irq(IRQ_LPC32XX_TIMER0, &lpc32xx_timer_irq);
> +
> +	/* Setup the clockevent structure. */
> +	lpc32xx_clkevt.mult = div_sc(clkrate, NSEC_PER_SEC,
> +		lpc32xx_clkevt.shift);
> +	lpc32xx_clkevt.max_delta_ns = clockevent_delta2ns(-1,
> +		&lpc32xx_clkevt);
> +	lpc32xx_clkevt.min_delta_ns = clockevent_delta2ns(1,
> +		&lpc32xx_clkevt) + 1;
> +	lpc32xx_clkevt.cpumask = cpumask_of(0);
> +	clockevents_register_device(&lpc32xx_clkevt);
> +
> +	/* Use timer1 as clock source. */
> +	__raw_writel(LCP32XX_TIMER_CNTR_TCR_RESET,
> +		LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
> +	__raw_writel(0, LCP32XX_TIMER_PR(LPC32XX_TIMER1_BASE));
> +	__raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE));
> +	__raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
> +		LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
> +	lpc32xx_clksrc.mult = clocksource_hz2mult(clkrate,
> +		lpc32xx_clksrc.shift);
> +	clocksource_register(&lpc32xx_clksrc);
> +}
> +
> +struct sys_timer lpc32xx_timer = {
> +	.init		= &lpc32xx_timer_init,
> +};
> +
Best regards
Uwe

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

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

* Re: [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
  2010-02-09  9:59     ` Russell King - ARM Linux
@ 2010-02-09 16:52         ` Uwe Kleine-König
  0 siblings, 0 replies; 44+ messages in thread
From: Uwe Kleine-König @ 2010-02-09 16:52 UTC (permalink / raw)
  To: Russell King - ARM Linux; +Cc: linux-arm-kernel, wellsk40, linux-sparse

[Added linux-sparse@vger.kernel.org to Cc:]

On Tue, Feb 09, 2010 at 09:59:34AM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 09, 2010 at 10:31:29AM +0100, Uwe Kleine-König wrote:
> > > +#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
> > Is this cast to unsigned long needed?  AFAIK IO_ADDRESS(x) has
> > type unsigned for x in { 0x0 ... 0xffffffff } (provided that int uses a
> > 32 bit 2s-complement representation).  If unsigned long is really
> > needed, maybe put it into the IO_ADDRESS macro?
> 
> int -> void __iomem * = sparse warning
> unsigned long -> void __iomem * = no sparse warning
Ah, OK, I see.  But IMHO it's a poor reason to add the cast.  Either
the cast is necessary/recommended or sparse is wrong.  In the first case
the reasoning shouldn't have to do with sparse, in the latter sparse
should be fixed.

I found the responsible code in sparse.  It reads:

	static struct symbol *evaluate_cast(struct expression *expr)
	{
		int as1 = 0, as2 = 0;
		...
		ctype = examine_symbol_type(expr->cast_type);
		...
		class1 = classify_type(ctype, &t1);
		...
		if (t1 == &ulong_ctype)
			as1 = -1;
		else if (class1 == TYPE_PTR) {
			examine_pointer_target(t1);
			as1 = t1->ctype.as;
		}
		
		if (t2 == &ulong_ctype)
			as2 = -1;
		else if (class2 == TYPE_PTR) {
			examine_pointer_target(t2);
			as2 = t2->ctype.as;
		}
		...
		if (as1 > 0 && !as2 &&
		    !is_null_pointer_constant(target) && Wcast_to_as)
			warning(expr->pos,
				"cast adds address space to expression (<asn:%d>)", as1);

so it seems to be explicitly allowed to make a pointer in any address
space from an unsigned long, but not from a (signed or unsigned) int.
Unfortunately there is no comment describing why unsigned long is
allowed.

Is this intended?  What is the preferred way to define iomem pointers?

I found the following variants in the kernel[1]

	#define ...	((void __iomem *)(unsigned long)0x12345678)
	#define ...	((void __iomem __force *)0x12345678)
	#define ...	((void __iomem *)0x12345678)

where __iomem is defined as __attribute__((noderef, address_space(2)))
for sparse.

The first variant with the extra cast to unsigned long seems unnecessary
long, the third results in the "cast adds address space to expression"
warning.

So what do you recommend?

Best regards and thanks
Uwe

[1] I only checked a few files, so maybe there are more.
-- 
Pengutronix e.K.                           | Uwe Kleine-König            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
@ 2010-02-09 16:52         ` Uwe Kleine-König
  0 siblings, 0 replies; 44+ messages in thread
From: Uwe Kleine-König @ 2010-02-09 16:52 UTC (permalink / raw)
  To: linux-arm-kernel

[Added linux-sparse at vger.kernel.org to Cc:]

On Tue, Feb 09, 2010 at 09:59:34AM +0000, Russell King - ARM Linux wrote:
> On Tue, Feb 09, 2010 at 10:31:29AM +0100, Uwe Kleine-K?nig wrote:
> > > +#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
> > Is this cast to unsigned long needed?  AFAIK IO_ADDRESS(x) has
> > type unsigned for x in { 0x0 ... 0xffffffff } (provided that int uses a
> > 32 bit 2s-complement representation).  If unsigned long is really
> > needed, maybe put it into the IO_ADDRESS macro?
> 
> int -> void __iomem * = sparse warning
> unsigned long -> void __iomem * = no sparse warning
Ah, OK, I see.  But IMHO it's a poor reason to add the cast.  Either
the cast is necessary/recommended or sparse is wrong.  In the first case
the reasoning shouldn't have to do with sparse, in the latter sparse
should be fixed.

I found the responsible code in sparse.  It reads:

	static struct symbol *evaluate_cast(struct expression *expr)
	{
		int as1 = 0, as2 = 0;
		...
		ctype = examine_symbol_type(expr->cast_type);
		...
		class1 = classify_type(ctype, &t1);
		...
		if (t1 == &ulong_ctype)
			as1 = -1;
		else if (class1 == TYPE_PTR) {
			examine_pointer_target(t1);
			as1 = t1->ctype.as;
		}
		
		if (t2 == &ulong_ctype)
			as2 = -1;
		else if (class2 == TYPE_PTR) {
			examine_pointer_target(t2);
			as2 = t2->ctype.as;
		}
		...
		if (as1 > 0 && !as2 &&
		    !is_null_pointer_constant(target) && Wcast_to_as)
			warning(expr->pos,
				"cast adds address space to expression (<asn:%d>)", as1);

so it seems to be explicitly allowed to make a pointer in any address
space from an unsigned long, but not from a (signed or unsigned) int.
Unfortunately there is no comment describing why unsigned long is
allowed.

Is this intended?  What is the preferred way to define iomem pointers?

I found the following variants in the kernel[1]

	#define ...	((void __iomem *)(unsigned long)0x12345678)
	#define ...	((void __iomem __force *)0x12345678)
	#define ...	((void __iomem *)0x12345678)

where __iomem is defined as __attribute__((noderef, address_space(2)))
for sparse.

The first variant with the extra cast to unsigned long seems unnecessary
long, the third results in the "cast adds address space to expression"
warning.

So what do you recommend?

Best regards and thanks
Uwe

[1] I only checked a few files, so maybe there are more.
-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH 05/14] ARM: LPC32XX: System suspend support
  2010-02-09  0:11 ` [PATCH 05/14] ARM: LPC32XX: System suspend support wellsk40 at gmail.com
@ 2010-02-09 17:03   ` Uwe Kleine-König
  2010-02-09 19:18     ` Kevin Wells
  2010-02-14 16:51   ` Pavel Machek
  1 sibling, 1 reply; 44+ messages in thread
From: Uwe Kleine-König @ 2010-02-09 17:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 08, 2010 at 04:11:26PM -0800, wellsk40 at gmail.com wrote:
> From: Kevin Wells <wellsk40@gmail.com>
> 
> Support for system suspend and resume
> 
> Signed-off-by: Kevin Wells <wellsk40@gmail.com>
> ---
>  arch/arm/mach-lpc32xx/pm.c      |  155 ++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-lpc32xx/suspend.S |  165 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 320 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-lpc32xx/pm.c b/arch/arm/mach-lpc32xx/pm.c
> new file mode 100644
> index 0000000..7480976
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/pm.c
> @@ -0,0 +1,155 @@
> +/*
> + * arch/arm/mach-lpc32xx/pm.c
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + * Based in part on PNX4008 power management code
... which has 2005 (c) MontaVista Software, Inc. and only allows GPLv2.

IMHO you should mention the copyright of the work this is based on and I
think you cannot allow GPLv2+ then (but INAL).

> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +/*
> + * LPC32XX CPU and system power management
> + *
> + * The LCP32XX has three CPU modes for controlling system power: run,
> + * direct-run, and halt modes. When switching between halt and run modes,
> + * the CPU transistions through direct-run mode. For Linux, direct-run
> + * mode is not used in normal operation. Halt mode is used when the
> + * system is fully suspended.
> + *
> + * Run mode:
> + * The ARM CPU clock (HCLK_PLL), HCLK bus clock, and PCLK bus clocks are
> + * derived from the HCLK PLL. The HCLK and PCLK bus rates are divided from
> + * the HCLK_PLL rate. Linux runs in this mode.
> + *
> + * Direct-run mode:
> + * The ARM CPU clock, HCLK bus clock, and PCLK bus clocks are driven from
> + * SYSCLK. SYSCLK is usually around 13MHz, but may vary based on SYSCLK
> + * source or the frequency of the main oscillator. In this mode, the
> + * HCLK_PLL can be safely enabled, changed, or disabled.
> + *
> + * Halt mode:
> + * SYSCLK is gated off and the CPU and system clocks are halted.
> + * Peripherals based on the 32KHz oscillator clock (ie, RTC, touch,
> + * key scanner, etc.) still operate if enabled. In this state, an enabled
> + * system event (ie, GPIO state change, RTC match, key press, etc.) will
> + * wake the system up back into direct-run mode.
> + *
> + * DRAM refresh
> + * DRAM clocking and refresh are slightly different for systems with DDR
> + * DRAM or regular SDRAM devices. If SDRAM is used in the system, the
> + * SDRAM will still be accessible in direct-run mode. In DDR based systems,
> + * a transistion to direct-run mode will stop all DDR accesses (no clocks).
> + * Because of this, the code to switch power modes and the code to enter
> + * and exit DRAM self-refresh modes must not be executed in DRAM. A small
> + * section of IRAM is used instead for this.
> + *
> + * Suspend is handled with the following logic:
> + *  Backup a small area of IRAM used for the suspend code
> + *  Copy suspend code to IRAM
> + *  Transfer control to code in IRAM
> + *  Places DRAMs in self-refresh mode
> + *  Enter direct-run mode
> + *  Save state of HCLK_PLL PLL
> + *  Disable HCLK_PLL PLL
> + *  Enter halt mode - CPU and buses will stop
> + *  System enters direct-run mode when an enabled event occurs
> + *  HCLK PLL state is restored
> + *  Run mode is entered
> + *  DRAMS are placed back into normal mode
> + *  Code execution returns from IRAM
> + *  IRAM code are used for suspend is restored
> + *  Suspend mode is exited
> + */
> +
> +#include <linux/suspend.h>
> +#include <linux/io.h>
> +
> +#include <asm/cacheflush.h>
> +
> +#include <mach/hardware.h>
> +#include <mach/platform.h>
> +#include "common.h"
> +#include "clock.h"
> +
> +#define TEMP_IRAM_AREA  IO_ADDRESS(LPC32XX_IRAM_BASE)
> +
> +static int lpc32xx_pm_valid_state(suspend_state_t state)
> +{
> +	return (state == PM_SUSPEND_MEM);
> +}
You can remove this function and use suspend_valid_only_mem instead.

> +
> +/*
> + * Both STANDBY and MEM suspend states are handled the same with no
> + * loss of CPU or memory state
This is an old comment.  STANDBY isn't used anymore.
> + */
> +static int lpc32xx_pm_enter(suspend_state_t state)
> +{
> +	int (*lpc32xx_suspend_ptr) (void);
> +	void *iram_swap_area;
> +
> +	/* Allocate some space for temporary IRAM storage */
> +	iram_swap_area = kmalloc(lpc32xx_sys_suspend_sz, GFP_KERNEL);
> +	if (!iram_swap_area) {
> +		printk(KERN_ERR
> +		       "PM Suspend: cannot allocate memory to save portion "
> +			"of SRAM\n");
> +		return -ENOMEM;
> +	}
> +
> +	/* Backup a small area of IRAM used for the suspend code */
> +	memcpy(iram_swap_area, (void *) TEMP_IRAM_AREA,
> +		lpc32xx_sys_suspend_sz);
> +	flush_cache_all();
> +
> +	/*
> +	 * Copy code to suspend system into IRAM. The suspend code
> +	 * needs to run from IRAM as DRAM may no longer be available
> +	 * when the PLL is stopped.
> +	 */
> +	memcpy((void *) TEMP_IRAM_AREA, &lpc32xx_sys_suspend,
> +		lpc32xx_sys_suspend_sz);
> +
> +	/* Transfer to suspend code in IRAM */
> +	lpc32xx_suspend_ptr = (void *) TEMP_IRAM_AREA;
> +	(void) lpc32xx_suspend_ptr();
> +
> +	/* Restore original IRAM contents */
> +	memcpy((void *) TEMP_IRAM_AREA, iram_swap_area,
> +		lpc32xx_sys_suspend_sz);
> +
> +	kfree(iram_swap_area);
> +
> +	return 0;
> +}
> +
> +static struct platform_suspend_ops lpc32xx_pm_ops = {
> +	.valid	= lpc32xx_pm_valid_state,
> +	.enter	= lpc32xx_pm_enter,
> +};
> +
> +#define EMC_DYN_MEM_CTRL_OFS 0x20
> +#define EMC_SRMMC           (1 << 3)
> +#define EMC_CTRL_REG io_p2v(LPC32XX_EMC_BASE + EMC_DYN_MEM_CTRL_OFS)
> +static int __init lpc32xx_pm_init(void)
> +{
> +	/*
> +	 * Setup SDRAM self-refresh clock to automatically
> +	 * disable on start of self-refresh
> +	 */
> +	__raw_writel(__raw_readl(EMC_CTRL_REG) | EMC_SRMMC, EMC_CTRL_REG);
Hmmm, is it correct to do this here?  Or should that go to the enter
function?  The thing is that this is a register setting that depends on
CONFIG_PM and not on having put the machine in a sleeping state.
> +
> +	suspend_set_ops(&lpc32xx_pm_ops);
> +
> +	return 0;
> +}
> +arch_initcall(lpc32xx_pm_init);
> diff --git a/arch/arm/mach-lpc32xx/suspend.S b/arch/arm/mach-lpc32xx/suspend.S
> new file mode 100644
> index 0000000..01c02ce
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/suspend.S
> @@ -0,0 +1,165 @@
> +/*
> + * arch/arm/mach-lpc32xx/suspend.S
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + * Based in part on PNX4008 power management code
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +#include <linux/linkage.h>
> +#include <asm/assembler.h>
> +#include <mach/platform.h>
> +#include <mach/hardware.h>
> +
> +/* Using named register defines makes the code easier to follow */
> +#define WORK1_REG			r0
> +#define WORK2_REG			r1
> +#define SAVED_HCLK_DIV_REG		r2
> +#define SAVED_HCLK_PLL_REG		r3
> +#define SAVED_DRAM_CLKCTRL_REG		r4
> +#define SAVED_PWR_CTRL_REG		r5
> +#define CLKPWRBASE_REG			r6
> +#define EMCBASE_REG			r7
> +
> +#define LPC32XX_EMC_STATUS_OFFS		0x04
> +#define LPC32XX_EMC_STATUS_BUSY		0x1
> +#define LPC32XX_EMC_STATUS_SELF_RFSH	0x4
> +
> +#define LPC32XX_CLKPWR_PWR_CTRL_OFFS	0x44
> +#define LPC32XX_CLKPWR_HCLK_DIV_OFFS	0x40
> +#define LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS 0x58
> +
> +#define CLKPWR_PCLK_DIV_MASK		0xFFFFFE7F
> +
> +	.text
> +
> +ENTRY(lpc32xx_sys_suspend)
> +	@ Save a copy of the used registers in IRAM, r0 is corrupted
> +	adr	r0, tmp_stack_end
> +	stmfd	r0!, {r1 - r7, sp, lr}
not that is matters much, but I think you don't need to save all of
these.  E.g. r0-r2 are allowed to be corrupted by functions.

> +
> +	@ Load a few common register addresses
> +	adr	WORK1_REG, reg_bases
> +	ldr	CLKPWRBASE_REG, [WORK1_REG, #0]
> +	ldr	EMCBASE_REG, [WORK1_REG, #4]
> +
> +	ldr	SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\
> +		#LPC32XX_CLKPWR_PWR_CTRL_OFFS]
> +	orr	WORK1_REG, SAVED_PWR_CTRL_REG, #LPC32XX_CLKPWR_SDRAM_SELF_RFSH
> +
> +	@ Wait for SDRAM busy status to go busy and then idle
> +	@ This guarantees a small windows where DRAM isn't busy
> +1:
> +	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
> +	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
> +	cmp	WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
> +	bne	1b @ Branch while idle
> +2:
> +	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
> +	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
> +	cmp	WORK2_REG, #LPC32XX_EMC_STATUS_BUSY
> +	beq	2b @ Branch until idle
> +
> +	@ Setup self-refresh with support for manual exit of
> +	@ self-refresh mode
> +	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
> +	orr	WORK2_REG, WORK1_REG, #LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH
> +	str	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
> +	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
> +
> +	@ Wait for self-refresh acknowledge, clocks to the DRAM device
> +	@ will automatically stop on start of self-refresh
> +3:
> +	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
> +	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH
> +	cmp	WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH
> +	bne	3b @ Branch until self-refresh mode starts
> +
> +	@ Enter direct-run mode from run mode
> +	bic	WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_SELECT_RUN_MODE
> +	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
> +
> +	@ Safe disable of DRAM clock in EMC block, prevents DDR sync
> +	@ issues on restart
> +	ldr	SAVED_HCLK_DIV_REG, [CLKPWRBASE_REG,\
> +		#LPC32XX_CLKPWR_HCLK_DIV_OFFS]
> +	and	WORK2_REG, SAVED_HCLK_DIV_REG, #CLKPWR_PCLK_DIV_MASK
> +	str	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLK_DIV_OFFS]
> +
> +	@ Save HCLK PLL state and disable HCLK PLL
> +	ldr	SAVED_HCLK_PLL_REG, [CLKPWRBASE_REG,\
> +		#LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
> +	bic	WORK2_REG, SAVED_HCLK_PLL_REG, #LPC32XX_CLKPWR_HCLKPLL_POWER_UP
> +	str	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
> +
> +	@ Enter stop mode until an enabled event occurs
> +	orr	WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_STOP_MODE_CTRL
> +	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
> +	nop
You can make this

	.rept 9
	nop
	.endr

> +
> +	@ Clear stop status
> +	bic	WORK1_REG, WORK1_REG, #LPC32XX_CLKPWR_STOP_MODE_CTRL
> +
> +	@ Restore original HCLK PLL value and wait for PLL lock
> +	str	SAVED_HCLK_PLL_REG, [CLKPWRBASE_REG,\
> +		#LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
> +4:
> +	ldr	WORK2_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_HCLKPLL_CTRL_OFFS]
> +	and	WORK2_REG, WORK2_REG, #LPC32XX_CLKPWR_HCLKPLL_PLL_STS
> +	bne	4b
> +
> +	@ Re-enter run mode with self-refresh flag cleared, but no DRAM
> +	@ update yet. DRAM is still in self-refresh
> +	str	SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\
> +		#LPC32XX_CLKPWR_PWR_CTRL_OFFS]
> +
> +	@ Restore original DRAM clock mode to restore DRAM clocks
> +	str	SAVED_HCLK_DIV_REG, [CLKPWRBASE_REG,\
> +		#LPC32XX_CLKPWR_HCLK_DIV_OFFS]
> +
> +	@ Clear self-refresh mode
> +	orr	WORK1_REG, SAVED_PWR_CTRL_REG,\
> +		#LPC32XX_CLKPWR_UPD_SDRAM_SELF_RFSH
> +	str	WORK1_REG, [CLKPWRBASE_REG, #LPC32XX_CLKPWR_PWR_CTRL_OFFS]
> +	str	SAVED_PWR_CTRL_REG, [CLKPWRBASE_REG,\
> +		#LPC32XX_CLKPWR_PWR_CTRL_OFFS]
> +
> +	@ Wait for EMC to clear self-refresh mode
> +5:
> +	ldr	WORK2_REG, [EMCBASE_REG, #LPC32XX_EMC_STATUS_OFFS]
> +	and	WORK2_REG, WORK2_REG, #LPC32XX_EMC_STATUS_SELF_RFSH
> +	bne	5b @ Branch until self-refresh has exited
> +
> +	@ restore regs and return
> +	adr	r0, tmp_stack
> +	ldmfd	r0!, {r1 - r7, sp, pc}
> +
> +reg_bases:
> +	.long	IO_ADDRESS(LPC32XX_CLK_PM_BASE)
> +	.long	IO_ADDRESS(LPC32XX_EMC_BASE)
> +
> +tmp_stack:
> +	.long	0, 0, 0, 0, 0, 0, 0, 0, 0
> +tmp_stack_end:
> +
> +ENTRY(lpc32xx_sys_suspend_sz)
> +	.word	. - lpc32xx_sys_suspend
> +
trailing newline

Best regards
Uwe

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

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

* RE: [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
  2010-02-09 16:52         ` Uwe Kleine-König
@ 2010-02-09 17:10           ` H Hartley Sweeten
  -1 siblings, 0 replies; 44+ messages in thread
From: H Hartley Sweeten @ 2010-02-09 17:10 UTC (permalink / raw)
  To: Uwe Kleine-König, Russell King - ARM Linux
  Cc: linux-sparse, linux-arm-kernel, wellsk40

On Tuesday, February 09, 2010 9:52 AM, Uwe Kleine-König wrote:
> [Added linux-sparse@vger.kernel.org to Cc:]
>
> On Tue, Feb 09, 2010 at 09:59:34AM +0000, Russell King - ARM Linux wrote:
>> On Tue, Feb 09, 2010 at 10:31:29AM +0100, Uwe Kleine-König wrote:
>>>> +#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
>>> Is this cast to unsigned long needed?  AFAIK IO_ADDRESS(x) has
>>> type unsigned for x in { 0x0 ... 0xffffffff } (provided that int uses a
>>> 32 bit 2s-complement representation).  If unsigned long is really
>>> needed, maybe put it into the IO_ADDRESS macro?
>> 
>> int -> void __iomem * = sparse warning
>> unsigned long -> void __iomem * = no sparse warning
> Ah, OK, I see.  But IMHO it's a poor reason to add the cast.  Either
> the cast is necessary/recommended or sparse is wrong.  In the first case
> the reasoning shouldn't have to do with sparse, in the latter sparse
> should be fixed.
>
> I found the responsible code in sparse.  It reads:

[snip]

> so it seems to be explicitly allowed to make a pointer in any address
> space from an unsigned long, but not from a (signed or unsigned) int.
> Unfortunately there is no comment describing why unsigned long is
> allowed.
>
> Is this intended?  What is the preferred way to define iomem pointers?
>
> I found the following variants in the kernel[1]
>
>	#define ...	((void __iomem *)(unsigned long)0x12345678)
>	#define ...	((void __iomem __force *)0x12345678)
>	#define ...	((void __iomem *)0x12345678)
>
> where __iomem is defined as __attribute__((noderef, address_space(2)))
> for sparse.
>
> The first variant with the extra cast to unsigned long seems unnecessary
> long, the third results in the "cast adds address space to expression"
> warning.
>
> So what do you recommend?

Would this fix the third variant?

	#define ... ((void __iomem *)0x12345678UL)

Regards,
Hartley

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

* [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
@ 2010-02-09 17:10           ` H Hartley Sweeten
  0 siblings, 0 replies; 44+ messages in thread
From: H Hartley Sweeten @ 2010-02-09 17:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday, February 09, 2010 9:52 AM, Uwe Kleine-K?nig wrote:
> [Added linux-sparse at vger.kernel.org to Cc:]
>
> On Tue, Feb 09, 2010 at 09:59:34AM +0000, Russell King - ARM Linux wrote:
>> On Tue, Feb 09, 2010 at 10:31:29AM +0100, Uwe Kleine-K?nig wrote:
>>>> +#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
>>> Is this cast to unsigned long needed?  AFAIK IO_ADDRESS(x) has
>>> type unsigned for x in { 0x0 ... 0xffffffff } (provided that int uses a
>>> 32 bit 2s-complement representation).  If unsigned long is really
>>> needed, maybe put it into the IO_ADDRESS macro?
>> 
>> int -> void __iomem * = sparse warning
>> unsigned long -> void __iomem * = no sparse warning
> Ah, OK, I see.  But IMHO it's a poor reason to add the cast.  Either
> the cast is necessary/recommended or sparse is wrong.  In the first case
> the reasoning shouldn't have to do with sparse, in the latter sparse
> should be fixed.
>
> I found the responsible code in sparse.  It reads:

[snip]

> so it seems to be explicitly allowed to make a pointer in any address
> space from an unsigned long, but not from a (signed or unsigned) int.
> Unfortunately there is no comment describing why unsigned long is
> allowed.
>
> Is this intended?  What is the preferred way to define iomem pointers?
>
> I found the following variants in the kernel[1]
>
>	#define ...	((void __iomem *)(unsigned long)0x12345678)
>	#define ...	((void __iomem __force *)0x12345678)
>	#define ...	((void __iomem *)0x12345678)
>
> where __iomem is defined as __attribute__((noderef, address_space(2)))
> for sparse.
>
> The first variant with the extra cast to unsigned long seems unnecessary
> long, the third results in the "cast adds address space to expression"
> warning.
>
> So what do you recommend?

Would this fix the third variant?

	#define ... ((void __iomem *)0x12345678UL)

Regards,
Hartley

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

* Re: [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
  2010-02-09 16:52         ` Uwe Kleine-König
@ 2010-02-09 17:58           ` Russell King - ARM Linux
  -1 siblings, 0 replies; 44+ messages in thread
From: Russell King - ARM Linux @ 2010-02-09 17:58 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: linux-arm-kernel, wellsk40, linux-sparse

On Tue, Feb 09, 2010 at 05:52:23PM +0100, Uwe Kleine-König wrote:
> [Added linux-sparse@vger.kernel.org to Cc:]
> 
> On Tue, Feb 09, 2010 at 09:59:34AM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 09, 2010 at 10:31:29AM +0100, Uwe Kleine-König wrote:
> > > > +#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
> > > Is this cast to unsigned long needed?  AFAIK IO_ADDRESS(x) has
> > > type unsigned for x in { 0x0 ... 0xffffffff } (provided that int uses a
> > > 32 bit 2s-complement representation).  If unsigned long is really
> > > needed, maybe put it into the IO_ADDRESS macro?
> > 
> > int -> void __iomem * = sparse warning
> > unsigned long -> void __iomem * = no sparse warning
> Ah, OK, I see.  But IMHO it's a poor reason to add the cast.  Either
> the cast is necessary/recommended or sparse is wrong.  In the first case
> the reasoning shouldn't have to do with sparse, in the latter sparse
> should be fixed.

The point is that on 64-bit architectures, a pointer may be representable
by an unsigned long, but not an int.

> Is this intended?  What is the preferred way to define iomem pointers?

Define a numerical address with a UL suffix is the simplest way.
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
@ 2010-02-09 17:58           ` Russell King - ARM Linux
  0 siblings, 0 replies; 44+ messages in thread
From: Russell King - ARM Linux @ 2010-02-09 17:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 09, 2010 at 05:52:23PM +0100, Uwe Kleine-K?nig wrote:
> [Added linux-sparse at vger.kernel.org to Cc:]
> 
> On Tue, Feb 09, 2010 at 09:59:34AM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 09, 2010 at 10:31:29AM +0100, Uwe Kleine-K?nig wrote:
> > > > +#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
> > > Is this cast to unsigned long needed?  AFAIK IO_ADDRESS(x) has
> > > type unsigned for x in { 0x0 ... 0xffffffff } (provided that int uses a
> > > 32 bit 2s-complement representation).  If unsigned long is really
> > > needed, maybe put it into the IO_ADDRESS macro?
> > 
> > int -> void __iomem * = sparse warning
> > unsigned long -> void __iomem * = no sparse warning
> Ah, OK, I see.  But IMHO it's a poor reason to add the cast.  Either
> the cast is necessary/recommended or sparse is wrong.  In the first case
> the reasoning shouldn't have to do with sparse, in the latter sparse
> should be fixed.

The point is that on 64-bit architectures, a pointer may be representable
by an unsigned long, but not an int.

> Is this intended?  What is the preferred way to define iomem pointers?

Define a numerical address with a UL suffix is the simplest way.

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

* Re: [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
  2010-02-09 16:52         ` Uwe Kleine-König
                           ` (2 preceding siblings ...)
  (?)
@ 2010-02-09 18:22         ` Josh Triplett
  -1 siblings, 0 replies; 44+ messages in thread
From: Josh Triplett @ 2010-02-09 18:22 UTC (permalink / raw)
  To: Uwe Kleine-König
  Cc: Russell King - ARM Linux, linux-arm-kernel, wellsk40, linux-sparse

On Tue, Feb 09, 2010 at 05:52:23PM +0100, Uwe Kleine-König wrote:
> [Added linux-sparse@vger.kernel.org to Cc:]
> 
> On Tue, Feb 09, 2010 at 09:59:34AM +0000, Russell King - ARM Linux wrote:
> > On Tue, Feb 09, 2010 at 10:31:29AM +0100, Uwe Kleine-König wrote:
> > > > +#define io_p2v(x)	((void __iomem *) (unsigned long) IO_ADDRESS(x))
> > > Is this cast to unsigned long needed?  AFAIK IO_ADDRESS(x) has
> > > type unsigned for x in { 0x0 ... 0xffffffff } (provided that int uses a
> > > 32 bit 2s-complement representation).  If unsigned long is really
> > > needed, maybe put it into the IO_ADDRESS macro?
> > 
> > int -> void __iomem * = sparse warning
> > unsigned long -> void __iomem * = no sparse warning
> Ah, OK, I see.  But IMHO it's a poor reason to add the cast.  Either
> the cast is necessary/recommended or sparse is wrong.  In the first case
> the reasoning shouldn't have to do with sparse, in the latter sparse
> should be fixed.
>
> I found the responsible code in sparse.  It reads:
> 
> 	static struct symbol *evaluate_cast(struct expression *expr)
> 	{
> 		int as1 = 0, as2 = 0;
> 		...
> 		ctype = examine_symbol_type(expr->cast_type);
> 		...
> 		class1 = classify_type(ctype, &t1);
> 		...
> 		if (t1 == &ulong_ctype)
> 			as1 = -1;
> 		else if (class1 == TYPE_PTR) {
> 			examine_pointer_target(t1);
> 			as1 = t1->ctype.as;
> 		}
> 		
> 		if (t2 == &ulong_ctype)
> 			as2 = -1;
> 		else if (class2 == TYPE_PTR) {
> 			examine_pointer_target(t2);
> 			as2 = t2->ctype.as;
> 		}
> 		...
> 		if (as1 > 0 && !as2 &&
> 		    !is_null_pointer_constant(target) && Wcast_to_as)
> 			warning(expr->pos,
> 				"cast adds address space to expression (<asn:%d>)", as1);
> 
> so it seems to be explicitly allowed to make a pointer in any address
> space from an unsigned long, but not from a (signed or unsigned) int.
> Unfortunately there is no comment describing why unsigned long is
> allowed.
> 
> Is this intended?  What is the preferred way to define iomem pointers?
> 
> I found the following variants in the kernel[1]
> 
> 	#define ...	((void __iomem *)(unsigned long)0x12345678)
> 	#define ...	((void __iomem __force *)0x12345678)
> 	#define ...	((void __iomem *)0x12345678)
> 
> where __iomem is defined as __attribute__((noderef, address_space(2)))
> for sparse.
> 
> The first variant with the extra cast to unsigned long seems unnecessary
> long, the third results in the "cast adds address space to expression"
> warning.
> 
> So what do you recommend?

I don't know the reasoning behind allowing casts from unsigned long,
except perhaps to allow creating pointer literals, but explicitly
casting by way of unsigned long seems wrong.  In general, the couple of
places that legitimately convert addresses between address spaces should
use __force.

- Josh Triplett
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 01/14] ARM: LPC32XX: Initial architecture header files
  2010-02-09  9:31   ` Uwe Kleine-König
  2010-02-09  9:52     ` Uwe Kleine-König
  2010-02-09  9:59     ` Russell King - ARM Linux
@ 2010-02-09 19:17     ` Kevin Wells
  2 siblings, 0 replies; 44+ messages in thread
From: Kevin Wells @ 2010-02-09 19:17 UTC (permalink / raw)
  To: linux-arm-kernel

Thanks again Uwe for your time spent reviewing this and your
helpful comments!

> > diff --git a/arch/arm/mach-lpc32xx/include/mach/board.h b/arch/arm/mach-
> lpc32xx/include/mach/board.h
> > new file mode 100644
> > index 0000000..30424bc
> > --- /dev/null
> > +++ b/arch/arm/mach-lpc32xx/include/mach/board.h
> > @@ -0,0 +1,23 @@
> > +/*
> > + * arch/arm/mach-lpc32xx/include/mach/board.h
> > + *
> > + * Author: Kevin Wells <kevin.wells@nxp.com>
> > + *
> > + * Copyright (C) 2010 NXP Semiconductors
> > + *
> > + * 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.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +
> nitpick: there is an empty line too much.
> 
> > +#ifndef __ASM_ARCH_BOARD_H
> > +#define __ASM_ARCH_BOARD_H
> > +
> > +#endif
> Do you really need this file?
> 

This file is a place holder. most of the other drivers for this
platform are already complete and a few add structures to this
file that are shared via platform data. I can remove it, but
would have to replace it later so I prefer to keep it now.

> > diff --git a/arch/arm/mach-lpc32xx/include/mach/clkdev.h
> b/arch/arm/mach-lpc32xx/include/mach/clkdev.h
> > new file mode 100644
> > index 0000000..9bf0637
> > --- /dev/null
> > +++ b/arch/arm/mach-lpc32xx/include/mach/clkdev.h
> > @@ -0,0 +1,25 @@
> > +/*
> > + * arch/arm/mach-lpc32xx/include/mach/clkdev.h
> > + *
> > + * Author: Kevin Wells <kevin.wells@nxp.com>
> hmmm, I wonder why you use your nxp address here, but gmail in the
> S-o-b.
> 

Corporate email + corporate IT + outlook = lots of problems with mailing lists
I'll change that address in git too.

Kevin

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

* [PATCH 03/14] ARM: LPC32XX: Clock driver
  2010-02-09 10:39   ` Uwe Kleine-König
@ 2010-02-09 19:18     ` Kevin Wells
  2010-02-19  0:42     ` Kevin Wells
  1 sibling, 0 replies; 44+ messages in thread
From: Kevin Wells @ 2010-02-09 19:18 UTC (permalink / raw)
  To: linux-arm-kernel

> > +
> > +/*
> > + * Post divider values for PLLs based on selected register value
> > + */
> > +const u32 pll_postdivs[4] = {1, 2, 4, 8};
> make this static, too?
> 

This object is used in 2 files/functions for PLL rate computation and
PLL rate generation and is externally defined in common.h. I should
be able to move the other function that references this into clock.c,
it's a clock function too, and make things a little more simpler.

> > +static void local_clk_disable(struct clk *clk)
> > +{
> > +	/* Don't attempt to disable clock if it has no users */
> WARN_ON(clk->usecount <= 0)?
> 
> > +	if (clk->usecount > 0) {
> > +		clk->usecount--;
> > +
> > +		/* Only disable clock when it has no more users */
> > +		if ((clk->usecount == 0) && (clk->enable))
> > +			clk->enable(clk, 0);
> > +
> > +		/* Check parent clocks, they may need to be disabled too */
> > +		if (clk->parent)
> > +			local_clk_disable(clk->parent);
> > +	}
> > +}
> > +
> > +static int local_clk_enable(struct clk *clk)
> > +{
> > +	int ret = 0;
> > +
> > +	if (clk->usecount == 0) {
> > +		/* Enable parent clocks first */
> > +		if (clk->parent)
> > +			ret = local_clk_enable(clk->parent);
> > +
> > +		/* Enable clock on first use */
> > +		if ((ret == 0) && (clk->enable)) {
> > +			ret = clk->enable(clk, 1);
> > +			clk->usecount++;
> > +		}
> > +
> > +		/* Back out use counters if enable fails */
> > +		if (ret < 0)
> > +			local_clk_disable(clk);
> if enable failed there is no need to disable, is it?
> 
> And I think the reference counting is broken.
> 
> After
> 
> 	clk_enable(aclk);
> 	clk_enable(aclk);
> 	clk_disable(aclk);
> 
> aclk is disabled because usecount isn't increased if it is already >0!?
> 

Yes, this does seem broken. I will review and fix.

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

* [PATCH 05/14] ARM: LPC32XX: System suspend support
  2010-02-09 17:03   ` Uwe Kleine-König
@ 2010-02-09 19:18     ` Kevin Wells
  0 siblings, 0 replies; 44+ messages in thread
From: Kevin Wells @ 2010-02-09 19:18 UTC (permalink / raw)
  To: linux-arm-kernel

> > +++ b/arch/arm/mach-lpc32xx/pm.c
> > @@ -0,0 +1,155 @@
> > +/*
> > + * arch/arm/mach-lpc32xx/pm.c
> > + *
> > + * Author: Kevin Wells <kevin.wells@nxp.com>
> > + * Based in part on PNX4008 power management code
> ... which has 2005 (c) MontaVista Software, Inc. and only allows GPLv2.
> 
> IMHO you should mention the copyright of the work this is based on and I
> think you cannot allow GPLv2+ then (but INAL).

Thanks for bringing this up! Both pm.c and suspend.S are based on the
PNX4008 code with modifications. I've attempted to keep original
copyrights and references where needed, but this one slipped by. I'm
glad I at least had the source comment in there. For these files and the
few other files copied directly over from the pnx4008 platform (ie,
i2c.h), is this going to be a problem? We had intended to release our
files under GPL, but now have a few GPLv2 files mixed in. For the
changed files, can we safely add our copyright tag to the file along
with Montavistas?

> +#define EMC_CTRL_REG io_p2v(LPC32XX_EMC_BASE + EMC_DYN_MEM_CTRL_OFS) 
> +static int __init lpc32xx_pm_init(void) {
> +	/*
> +	 * Setup SDRAM self-refresh clock to automatically
> +	 * disable on start of self-refresh
> +	 */
> +	__raw_writel(__raw_readl(EMC_CTRL_REG) | EMC_SRMMC, EMC_CTRL_REG);
Hmmm, is it correct to do this here?  Or should that go to the enter function?  The thing is that this is a register setting that depends on CONFIG_PM and not on having put the machine in a sleeping state.

This is actually safe to do for configurations with or without PM
support, but is an absolute requirement for suspend to work. I would
prefer the bootloader handle this and always set this, but different
boards loaders do not always set this up the same (including ours,
which turns it off). Its ok to turn this on with CONFIG_PM support.

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

* [PATCH 12/14] AMBA: CLCD: LPC32XX register swap in the clcd header file
  2010-02-09  0:11 ` [PATCH 12/14] AMBA: CLCD: LPC32XX register swap in the clcd header file wellsk40 at gmail.com
@ 2010-02-12 14:31   ` Russell King - ARM Linux
  2010-02-12 16:32     ` Kevin Wells
  0 siblings, 1 reply; 44+ messages in thread
From: Russell King - ARM Linux @ 2010-02-12 14:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 08, 2010 at 04:11:33PM -0800, wellsk40 at gmail.com wrote:
> The CTRL and IENB registers need to be swapped for the LPC32XX
> arch.

Is your peripheral a PL110 or PL111 ?

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

* [PATCH 12/14] AMBA: CLCD: LPC32XX register swap in the clcd header file
  2010-02-12 14:31   ` Russell King - ARM Linux
@ 2010-02-12 16:32     ` Kevin Wells
  2010-02-12 16:41       ` Russell King - ARM Linux
  0 siblings, 1 reply; 44+ messages in thread
From: Kevin Wells @ 2010-02-12 16:32 UTC (permalink / raw)
  To: linux-arm-kernel

> 
> On Mon, Feb 08, 2010 at 04:11:33PM -0800, wellsk40 at gmail.com wrote:
> > The CTRL and IENB registers need to be swapped for the LPC32XX
> > arch.
> 
> Is your peripheral a PL110 or PL111 ?
> 

This part uses an unmodified PL111.

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

* [PATCH 12/14] AMBA: CLCD: LPC32XX register swap in the clcd header file
  2010-02-12 16:32     ` Kevin Wells
@ 2010-02-12 16:41       ` Russell King - ARM Linux
  2010-02-16 20:27         ` Kevin Wells
  0 siblings, 1 reply; 44+ messages in thread
From: Russell King - ARM Linux @ 2010-02-12 16:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Feb 12, 2010 at 05:32:58PM +0100, Kevin Wells wrote:
> > 
> > On Mon, Feb 08, 2010 at 04:11:33PM -0800, wellsk40 at gmail.com wrote:
> > > The CTRL and IENB registers need to be swapped for the LPC32XX
> > > arch.
> > 
> > Is your peripheral a PL110 or PL111 ?
> > 
> 
> This part uses an unmodified PL111.

In which case, could you test this patch please:

    Video: ARM CLCD: Better fix for swapped IENB and CNTL registers
    
    On PL111, as found on Realview and other platforms, these registers are
    always arranged as CNTL then IENB.  On PL110, these registers are IENB
    then CNTL, except on Versatile platforms.
    
    Re-arrange the handling of these register swaps so that PL111 always
    gets it right without resorting to ifdefs, leaving the only case needing
    special handling being PL110 on Versatile.
    
    Fill out amba/clcd.h with the PL110/PL111 register definition
    differences in case someone tries to use the PL110 specific definitions
    on PL111.
    
    Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

 drivers/video/amba-clcd.c |   31 ++++++++++++++++++++++++-------
 include/linux/amba/clcd.h |   33 +++++++++++++++++----------------
 2 files changed, 41 insertions(+), 23 deletions(-)

diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c
index a21efcd..afe21e6 100644
--- a/drivers/video/amba-clcd.c
+++ b/drivers/video/amba-clcd.c
@@ -65,16 +65,16 @@ static void clcdfb_disable(struct clcd_fb *fb)
 	if (fb->board->disable)
 		fb->board->disable(fb);
 
-	val = readl(fb->regs + CLCD_CNTL);
+	val = readl(fb->regs + fb->off_cntl);
 	if (val & CNTL_LCDPWR) {
 		val &= ~CNTL_LCDPWR;
-		writel(val, fb->regs + CLCD_CNTL);
+		writel(val, fb->regs + fb->off_cntl);
 
 		clcdfb_sleep(20);
 	}
 	if (val & CNTL_LCDEN) {
 		val &= ~CNTL_LCDEN;
-		writel(val, fb->regs + CLCD_CNTL);
+		writel(val, fb->regs + fb->off_cntl);
 	}
 
 	/*
@@ -94,7 +94,7 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
 	 * Bring up by first enabling..
 	 */
 	cntl |= CNTL_LCDEN;
-	writel(cntl, fb->regs + CLCD_CNTL);
+	writel(cntl, fb->regs + fb->off_cntl);
 
 	clcdfb_sleep(20);
 
@@ -102,7 +102,7 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
 	 * and now apply power.
 	 */
 	cntl |= CNTL_LCDPWR;
-	writel(cntl, fb->regs + CLCD_CNTL);
+	writel(cntl, fb->regs + fb->off_cntl);
 
 	/*
 	 * finally, enable the interface.
@@ -233,7 +233,7 @@ static int clcdfb_set_par(struct fb_info *info)
 		readl(fb->regs + CLCD_TIM0), readl(fb->regs + CLCD_TIM1),
 		readl(fb->regs + CLCD_TIM2), readl(fb->regs + CLCD_TIM3),
 		readl(fb->regs + CLCD_UBAS), readl(fb->regs + CLCD_LBAS),
-		readl(fb->regs + CLCD_IENB), readl(fb->regs + CLCD_CNTL));
+		readl(fb->regs + fb->off_ienb), readl(fb->regs + fb->off_cntl));
 #endif
 
 	return 0;
@@ -345,6 +345,23 @@ static int clcdfb_register(struct clcd_fb *fb)
 {
 	int ret;
 
+	/*
+	 * ARM PL111 always has IENB at 0x1c; it's only PL110
+	 * which is reversed on some platforms.
+	 */
+	if (amba_manf(fb->dev) == 0x41 && amba_part(fb->dev) == 0x111) {
+		fb->off_ienb = CLCD_PL111_IENB;
+		fb->off_cntl = CLCD_PL111_CNTL;
+	} else {
+#ifdef CONFIG_ARCH_VERSATILE
+		fb->off_ienb = CLCD_PL111_IENB;
+		fb->off_cntl = CLCD_PL111_CNTL;
+#else
+		fb->off_ienb = CLCD_PL110_IENB;
+		fb->off_cntl = CLCD_PL110_CNTL;
+#endif
+	}
+
 	fb->clk = clk_get(&fb->dev->dev, NULL);
 	if (IS_ERR(fb->clk)) {
 		ret = PTR_ERR(fb->clk);
@@ -416,7 +433,7 @@ static int clcdfb_register(struct clcd_fb *fb)
 	/*
 	 * Ensure interrupts are disabled.
 	 */
-	writel(0, fb->regs + CLCD_IENB);
+	writel(0, fb->regs + fb->off_ienb);
 
 	fb_set_var(&fb->fb, &fb->fb.var);
 
diff --git a/include/linux/amba/clcd.h b/include/linux/amba/clcd.h
index 29c0448..ca16c38 100644
--- a/include/linux/amba/clcd.h
+++ b/include/linux/amba/clcd.h
@@ -21,22 +21,21 @@
 #define CLCD_UBAS 		0x00000010
 #define CLCD_LBAS 		0x00000014
 
-#if !defined(CONFIG_ARCH_VERSATILE) && !defined(CONFIG_ARCH_REALVIEW)
-#define CLCD_IENB 		0x00000018
-#define CLCD_CNTL 		0x0000001c
-#else
-/*
- * Someone rearranged these two registers on the Versatile
- * platform...
- */
-#define CLCD_IENB 		0x0000001c
-#define CLCD_CNTL 		0x00000018
-#endif
-
-#define CLCD_STAT 		0x00000020
-#define CLCD_INTR 		0x00000024
-#define CLCD_UCUR 		0x00000028
-#define CLCD_LCUR 		0x0000002C
+#define CLCD_PL110_IENB		0x00000018
+#define CLCD_PL110_CNTL		0x0000001c
+#define CLCD_PL110_STAT		0x00000020
+#define CLCD_PL110_INTR 	0x00000024
+#define CLCD_PL110_UCUR		0x00000028
+#define CLCD_PL110_LCUR		0x0000002C
+
+#define CLCD_PL111_CNTL		0x00000018
+#define CLCD_PL111_IENB		0x0000001c
+#define CLCD_PL111_RIS		0x00000020
+#define CLCD_PL111_MIS		0x00000024
+#define CLCD_PL111_ICR		0x00000028
+#define CLCD_PL111_UCUR		0x0000002c
+#define CLCD_PL111_LCUR		0x00000030
+
 #define CLCD_PALL 		0x00000200
 #define CLCD_PALETTE		0x00000200
 
@@ -147,6 +146,8 @@ struct clcd_fb {
 	struct clcd_board	*board;
 	void			*board_data;
 	void __iomem		*regs;
+	u16			off_ienb;
+	u16			off_cntl;
 	u32			clcd_cntl;
 	u32			cmap[16];
 };

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

* [PATCH 07/14] ARM: LPC32XX: Misc support functions
  2010-02-09  0:11 ` [PATCH 07/14] ARM: LPC32XX: Misc support functions wellsk40 at gmail.com
@ 2010-02-12 20:06   ` Uwe Kleine-König
  0 siblings, 0 replies; 44+ messages in thread
From: Uwe Kleine-König @ 2010-02-12 20:06 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kevin,

> +/*
> + * Detects and returns IRAM size for the device variation
> + */
> +#define LPC32XX_IRAM_BANK_SIZE (128 * SZ_1K)
SZ_128K ?

> +static u32 iram_size;
> +u32 lpc32xx_return_iram_size(void)
> +{
> +	if (iram_size == 0) {
> +		u32 savedval;
> +		void __iomem *iramptr1, *iramptr2;
> +
> +		iramptr1 = io_p2v(LPC32XX_IRAM_BASE);
> +		iramptr2 = io_p2v(LPC32XX_IRAM_BASE + LPC32XX_IRAM_BANK_SIZE);
> +		savedval = __raw_readl(iramptr2);
> +
> +		__raw_writel(savedval + 1, iramptr2);
> +
> +		/*
> +		 * If IRAM size is 128K, the value at iramptr2 will wrap back
> +		 * into iramptr1
> +		 */
> +		if (__raw_readl(iramptr1) == __raw_readl(iramptr2))
> +			iram_size = LPC32XX_IRAM_BANK_SIZE;
> +		else
> +			iram_size = LPC32XX_IRAM_BANK_SIZE * 2;
> +
> +		__raw_writel(savedval, iramptr2);
> +	}
> +
> +	return iram_size;
> +}
I didn't understand this.  The size of IRAM is either 128KiB or 256KiB,
right.  And if it's 128KiB it's mirrored.

So if the content of a 256KiB IRAM happens to be

	00000:  00000001 ....
	...
	20000:  00000000 ....

the above code does

	savedval = 8
	IRAM[20000] = 1
	iram_size = LPC32XX_IRAM_BANK_SIZE;

IMHO you should do:

	savedval1 = __raw_readl(iramptr1);
	savedval2 = __raw_readl(iramptr2);

	if (savedval1 == savedval2) {
		__raw_writel(savedval2 + 1, iramptr2);
		if (__raw_readl(iramptr1) == savedval2 + 1)
			iram_size = LPC32XX_IRAM_BANK_SIZE;
		else
			iram_size = 2 * LPC32XX_IRAM_BANK_SIZE;
		__raw_writel(savedval2, iramptr2);
	} else
		iram_size = 2 * LPC32XX_IRAM_BANK_SIZE;

> diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h
> new file mode 100644
> index 0000000..8161efe
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/common.h
> @@ -0,0 +1,75 @@
> +/*
> + * arch/arm/mach-lpc32xx/common.h
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2009-2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#ifndef __LPC32XX_COMMON_H
> +#define __LPC32XX_COMMON_H
> +
> +#include <linux/platform_device.h>
> +
> +/*
> + * Arch specific platform device structures
> + */
> +extern struct platform_device watchdog_device;
lpc32xx_watchdoc_device?

> +extern struct platform_device i2c0_device;
> +extern struct platform_device i2c1_device;
> +extern struct platform_device i2c2_device;
I prefer using functions to add these devices because then it's easier
to add support for now SoCs that happen to have the watchdog at a
different address.  Then you can just do:

	static struct resource watchdog_resources[] __initdata = {
		{
			.flags = ...;
		},
	};
	int __init lpc32xx_add_watchdog(void)
	{
		if (cpu_is_lpc3212()) {
			watchdog_resources[0].start = LPC3212_WATCHDOG_BASE;
		} else if (cpu_is_lpc3214()) {
			watchdog_resources[0].start = LPC3214_WATCHDOG_BASE;
		} else
			return -ENODEV;

		watchdog_resources[0].end = watchdog_resources[0].start + SZ_4K;

		....

	}

or something similar.  Another variation is:

	static struct resource watchdog_resources[] __initdata = {
		...
	}

	int __init lpc32xx_add_watchdog(sometype baseaddr)
	{
		watchdog_resources[0].start = base;
		...
	}

and then in a header do:

	#define lpc3212_add_watchdog() lpc32xx_add_watchdog(LPC3212_WATCHDOG_BASE)
	#define lpc3214_add_watchdog() lpc32xx_add_watchdog(LPC3214_WATCHDOG_BASE)

or provide an inline function.

When providing platform_devices as in your patch you have to do:

	extern struct platform_device lpc3212_watchdog_device;
	extern struct platform_device lpc3214_watchdog_device;

and at least in a kernel that supports both SoCs one or the other only
sits in RAM doing nothing.

But YMMV.

Best regards
Uwe

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

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

* [PATCH 08/14] ARM: LPC32XX: Phytec 3250 platform support
  2010-02-09  0:11 ` [PATCH 08/14] ARM: LPC32XX: Phytec 3250 platform support wellsk40 at gmail.com
@ 2010-02-12 20:08   ` Uwe Kleine-König
  2010-02-16 19:43     ` Kevin Wells
  0 siblings, 1 reply; 44+ messages in thread
From: Uwe Kleine-König @ 2010-02-12 20:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Feb 08, 2010 at 04:11:29PM -0800, wellsk40 at gmail.com wrote:
> From: Kevin Wells <wellsk40@gmail.com>
> 
> Platform support file for the PHY3250 mach id
> 
> Signed-off-by: Kevin Wells <wellsk40@gmail.com>
> ---
>  arch/arm/mach-lpc32xx/phy3250.c |  385 +++++++++++++++++++++++++++++++++++++++
>  1 files changed, 385 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
> new file mode 100644
> index 0000000..62bdb62
> --- /dev/null
> +++ b/arch/arm/mach-lpc32xx/phy3250.c
> @@ -0,0 +1,385 @@
> +/*
> + * arch/arm/mach-lpc32xx/phy3250.c
> + *
> + * Author: Kevin Wells <kevin.wells@nxp.com>
> + *
> + * Copyright (C) 2010 NXP Semiconductors
> + *
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/platform_device.h>
> +#include <linux/sysdev.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/device.h>
> +#include <linux/spi/spi.h>
> +#include <linux/spi/eeprom.h>
> +#include <linux/leds.h>
> +#include <linux/gpio.h>
> +#include <linux/amba/bus.h>
> +#include <linux/amba/clcd.h>
> +#include <linux/amba/pl022.h>
> +
> +#include <asm/setup.h>
> +#include <asm/mach-types.h>
> +#include <asm/mach/arch.h>
> +
> +#include <mach/hardware.h>
> +#include <mach/platform.h>
> +#include <mach/board.h>
> +#include "common.h"
> +
> +/*
> + * Mapped GPIOLIB GPIOs
> + */
> +#define SPI0_CS_GPIO	LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
> +#define LCD_POWER_GPIO	LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0)
> +#define BKL_POWER_GPIO	LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4)
> +#define LED_GPIO	LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 1)
> +
> +/*
> + * AMBA LCD controller
> + */
> +static struct clcd_panel conn_lcd_panel = {
> +	.mode		= {
> +		.name		= "QVGA portrait",
> +		.refresh	= 60,
> +		.xres		= 240,
> +		.yres		= 320,
> +		.pixclock	= 191828,
> +		.left_margin	= 22,
> +		.right_margin	= 11,
> +		.upper_margin	= 2,
> +		.lower_margin	= 1,
> +		.hsync_len	= 5,
> +		.vsync_len	= 2,
> +		.sync		= 0,
> +		.vmode		= FB_VMODE_NONINTERLACED,
> +	},
> +	.width		= -1,
> +	.height		= -1,
> +	.tim2		= (TIM2_IVS | TIM2_IHS),
> +	.cntl		= (CNTL_BGR | CNTL_LCDTFT | CNTL_LCDVCOMP(1) |
> +				CNTL_LCDBPP16_565),
> +	.bpp		= 16,
> +};
> +#define PANEL_SIZE (3 * SZ_64K)
> +
> +static int lpc32xx_clcd_setup(struct clcd_fb *fb)
> +{
> +	dma_addr_t dma;
> +
> +	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev,
> +		PANEL_SIZE, &dma, GFP_KERNEL);
> +	if (!fb->fb.screen_base) {
> +		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
> +		return -ENOMEM;
> +	}
> +
> +	fb->fb.fix.smem_start = dma;
> +	fb->fb.fix.smem_len = PANEL_SIZE;
> +	fb->panel = &conn_lcd_panel;
> +
> +	gpio_request(LCD_POWER_GPIO, "LCD power");
> +	gpio_direction_output(LCD_POWER_GPIO, 1);
> +	gpio_request(BKL_POWER_GPIO, "LCD backlight power");
> +	gpio_direction_output(BKL_POWER_GPIO, 1);
I'd check the return values of the gpio_... functions.

> +
> +	return 0;
> +}
> +
> +static int lpc32xx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
> +{
> +	return dma_mmap_writecombine(&fb->dev->dev, vma,
> +		fb->fb.screen_base, fb->fb.fix.smem_start,
> +		fb->fb.fix.smem_len);
> +}
> +
> +static void lpc32xx_clcd_remove(struct clcd_fb *fb)
> +{
> +	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
> +		fb->fb.screen_base, fb->fb.fix.smem_start);
> +}
> +
> +/*
> + * On some early LCD modules (1307.0), the backlight logic is inverted.
> + * For those board variants, swap the disable and enable states for
> + * BKL_POWER_GPIO.
> +*/
> +static void clcd_disable(struct clcd_fb *fb)
> +{
> +	gpio_set_value(BKL_POWER_GPIO, 0);
> +	gpio_set_value(LCD_POWER_GPIO, 0);
> +}
> +
> +static void clcd_enable(struct clcd_fb *fb)
> +{
> +	gpio_set_value(BKL_POWER_GPIO, 1);
> +	gpio_set_value(LCD_POWER_GPIO, 1);
> +}
> +
> +static struct clcd_board lpc32xx_clcd_data = {
> +	.name		= "Phytec LCD",
> +	.check		= clcdfb_check,
> +	.decode		= clcdfb_decode,
> +	.disable	= clcd_disable,
> +	.enable		= clcd_enable,
> +	.setup		= lpc32xx_clcd_setup,
> +	.mmap		= lpc32xx_clcd_mmap,
> +	.remove		= lpc32xx_clcd_remove,
> +};
> +
> +static struct amba_device clcd_device = {
> +	.dev				= {
> +		.coherent_dma_mask	= ~0,
> +		.init_name		= "dev:clcd",
> +		.platform_data		= &lpc32xx_clcd_data,
> +	},
> +	.res				= {
> +		.start			= LPC32XX_LCD_BASE,
> +		.end			= (LPC32XX_LCD_BASE + SZ_4K - 1),
> +		.flags			= IORESOURCE_MEM,
> +	},
> +	.dma_mask			= ~0,
> +	.irq				= {IRQ_LPC32XX_LCD, NO_IRQ},
> +};
> +
> +/*
> + * AMBA SSP (SPI)
> + */
> +static void phy3250_spi_cs_set(u32 control)
> +{
> +	gpio_set_value(SPI0_CS_GPIO, (int) control);
> +}
> +
> +static struct pl022_config_chip spi0_chip_info = {
> +	.lbm			= LOOPBACK_DISABLED,
> +	.com_mode		= INTERRUPT_TRANSFER,
> +	.iface			= SSP_INTERFACE_MOTOROLA_SPI,
> +	.hierarchy		= SSP_MASTER,
> +	.slave_tx_disable	= 0,
> +	.endian_tx		= SSP_TX_LSB,
> +	.endian_rx		= SSP_RX_LSB,
> +	.data_size		= SSP_DATA_BITS_8,
> +	.rx_lev_trig		= SSP_RX_4_OR_MORE_ELEM,
> +	.tx_lev_trig		= SSP_TX_4_OR_MORE_EMPTY_LOC,
> +	.clk_phase		= SSP_CLK_FIRST_EDGE,
> +	.clk_pol		= SSP_CLK_POL_IDLE_LOW,
> +	.ctrl_len		= SSP_BITS_8,
> +	.wait_state		= SSP_MWIRE_WAIT_ZERO,
> +	.duplex			= SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
> +	.cs_control		= phy3250_spi_cs_set,
> +};
> +
> +static struct pl022_ssp_controller lpc32xx_ssp0_data = {
> +	.bus_id			= 0,
> +	.num_chipselect		= 1,
> +	.enable_dma		= 0,
> +};
> +
> +static struct amba_device ssp0_device = {
> +	.dev				= {
> +		.coherent_dma_mask	= ~0,
> +		.init_name		= "dev:ssp0",
> +		.platform_data		= &lpc32xx_ssp0_data,
> +	},
> +	.res				= {
> +		.start			= LPC32XX_SSP0_BASE,
> +		.end			= (LPC32XX_SSP0_BASE + SZ_4K - 1),
> +		.flags			= IORESOURCE_MEM,
> +	},
> +	.dma_mask			= ~0,
> +	.irq				= {IRQ_LPC32XX_SSP0, NO_IRQ},
> +};
> +
> +/* AT25 driver registration */
> +static int __init phy3250_spi_board_register(void)
> +{
> +#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
> +	static struct spi_board_info info[] = {
> +		{
> +			.modalias = "spidev",
> +			.max_speed_hz = 5000000,
> +			.bus_num = 0,
> +			.chip_select = 0,
> +			.controller_data = &spi0_chip_info,
> +		},
> +	};
> +
> +#else
> +	static struct spi_eeprom eeprom = {
> +		.name = "at25256a",
> +		.byte_len = 0x8000,
> +		.page_size = 64,
> +		.flags = EE_ADDR2,
> +	};
> +
> +	static struct spi_board_info info[] = {
> +		{
> +			.modalias = "at25",
> +			.max_speed_hz = 5000000,
> +			.bus_num = 0,
> +			.chip_select = 0,
> +			.platform_data = &eeprom,
> +			.controller_data = &spi0_chip_info,
> +		},
> +	};
> +#endif
> +	return spi_register_board_info(info, ARRAY_SIZE(info));
> +}
> +arch_initcall(phy3250_spi_board_register);
> +
> +static struct i2c_board_info __initdata phy3250_i2c_board_info[] = {
> +	{
> +		I2C_BOARD_INFO("pcf8563", 0x51),
> +	},
> +};
> +
> +static struct gpio_led phy_leds[] = {
> +	{
> +		.name			= "led0",
> +		.gpio			= LED_GPIO,
> +		.active_low		= 1,
> +		.default_trigger	= "heartbeat",
> +	},
> +};
> +
> +static struct gpio_led_platform_data led_data = {
> +	.leds = phy_leds,
> +	.num_leds = ARRAY_SIZE(phy_leds),
> +};
> +
> +static struct platform_device lpc32xx_gpio_led_device = {
> +	.name			= "leds-gpio",
> +	.id			= -1,
> +	.dev.platform_data	= &led_data,
> +};
> +
> +static struct platform_device *phy3250_devs[] __initdata = {
> +	&i2c0_device,
> +	&i2c1_device,
> +	&i2c2_device,
> +	&watchdog_device,
> +	&lpc32xx_gpio_led_device,
> +};
> +
> +static struct amba_device *amba_devs[] __initdata = {
> +	&clcd_device,
> +	&ssp0_device,
> +};
> +
> +/*
> + * Board specific functions
> + */
> +static void __init phy3250_board_init(void)
> +{
> +	u32 tmp;
> +	int i;
> +
> +	lpc32xx_gpio_init();
> +
> +	/* Register GPIOs used on this board */
> +	gpio_request(SPI0_CS_GPIO, "spi0 cs");
> +	gpio_direction_output(SPI0_CS_GPIO, 1);
> +
> +	/* Setup network interface for RMII mode */
> +	tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL);
> +	tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK;
> +	tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS;
> +	__raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL);
> +
> +	/* Setup SLC NAND controller muxing */
> +	__raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
> +		LPC32XX_CLKPWR_NAND_CLK_CTRL);
> +
> +	/* Setup LCD muxing to RGB565 */
> +	tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) &
> +		~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK |
> +		LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK);
> +	tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16;
> +	__raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL);
> +
> +	/* Set up I2C pull levels */
> +	tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
> +	tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE |
> +		LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE;
> +	__raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
> +
> +	/* Disable IrDA pulsing support on UART6 */
> +	tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
> +	tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS;
> +	__raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
> +
> +	/* Enable DMA for I2S1 channel */
> +	tmp = __raw_readl(LPC32XX_CLKPWR_I2S_CLK_CTRL);
> +	tmp = LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA;
> +	__raw_writel(tmp, LPC32XX_CLKPWR_I2S_CLK_CTRL);
> +
> +	lpc32xx_serial_init();
> +
> +	/*
> +	 * AMBA peripheral clocks need to be enabled prior to AMBA device
> +	 * detection or a data fault will occur, so enable the clocks
> +	 * here. However, we don't want to enable them if the peripheral
> +	 * isn't included in the image
> +	 */
> +#ifdef CONFIG_FB_ARMCLCD
> +	tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
> +	__raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN),
> +		LPC32XX_CLKPWR_LCDCLK_CTRL);
> +#endif
> +#ifdef CONFIG_SPI_PL022
> +	tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL);
> +	__raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN),
> +		LPC32XX_CLKPWR_SSP_CLK_CTRL);
> +#endif
> +
> +	platform_add_devices(phy3250_devs, ARRAY_SIZE(phy3250_devs));
> +	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
> +		struct amba_device *d = amba_devs[i];
> +		amba_device_register(d, &iomem_resource);
> +	}
> +
> +	/* Test clock needed for UDA1380 initial init */
> +	__raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC |
> +		LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
> +		LPC32XX_CLKPWR_TEST_CLK_SEL);
> +
> +	i2c_register_board_info(0, phy3250_i2c_board_info,
> +		ARRAY_SIZE(phy3250_i2c_board_info));
> +}
> +
> +static int __init lpc32xx_display_uid(void)
> +{
> +	u32 uid[4];
> +
> +	lpc32xx_get_uid(uid);
> +
> +	printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n",
> +		uid[3], uid[2], uid[1], uid[0]);
> +
> +	return 1;
> +}
> +arch_initcall(lpc32xx_display_uid);
> +
> +MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller")
> +	/* Maintainer: Kevin Wells, NXP Semiconductors */
> +	.phys_io	= LPC32XX_UART5_BASE,
> +	.io_pg_offst	= ((IO_ADDRESS(LPC32XX_UART5_BASE))>>18) & 0xfffc,
> +	.boot_params	= 0x80000100,
> +	.map_io		= lpc32xx_map_io,
> +	.init_irq	= lpc32xx_init_irq,
> +	.timer		= &lpc32xx_timer,
> +	.init_machine	= phy3250_board_init,
> +MACHINE_END

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

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

* [PATCH 05/14] ARM: LPC32XX: System suspend support
  2010-02-09  0:11 ` [PATCH 05/14] ARM: LPC32XX: System suspend support wellsk40 at gmail.com
  2010-02-09 17:03   ` Uwe Kleine-König
@ 2010-02-14 16:51   ` Pavel Machek
  2010-02-14 19:45     ` Russell King - ARM Linux
  1 sibling, 1 reply; 44+ messages in thread
From: Pavel Machek @ 2010-02-14 16:51 UTC (permalink / raw)
  To: linux-arm-kernel

Hi!

> Support for system suspend and resume
> 
> Signed-off-by: Kevin Wells <wellsk40@gmail.com>
> ---


> +	/* Backup a small area of IRAM used for the suspend code */
> +	memcpy(iram_swap_area, (void *) TEMP_IRAM_AREA,
> +		lpc32xx_sys_suspend_sz);
> +	flush_cache_all();
> +
> +	/*
> +	 * Copy code to suspend system into IRAM. The suspend code
> +	 * needs to run from IRAM as DRAM may no longer be available
> +	 * when the PLL is stopped.
> +	 */
> +	memcpy((void *) TEMP_IRAM_AREA, &lpc32xx_sys_suspend,
> +		lpc32xx_sys_suspend_sz);

icache flush needed here? or does the above flush suffice? ... I
believe you do need the flush.

> +	/* Transfer to suspend code in IRAM */
> +	lpc32xx_suspend_ptr = (void *) TEMP_IRAM_AREA;
> +	(void) lpc32xx_suspend_ptr();
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

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

* [PATCH 05/14] ARM: LPC32XX: System suspend support
  2010-02-14 16:51   ` Pavel Machek
@ 2010-02-14 19:45     ` Russell King - ARM Linux
  0 siblings, 0 replies; 44+ messages in thread
From: Russell King - ARM Linux @ 2010-02-14 19:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Feb 14, 2010 at 05:51:22PM +0100, Pavel Machek wrote:
> > +	/* Backup a small area of IRAM used for the suspend code */
> > +	memcpy(iram_swap_area, (void *) TEMP_IRAM_AREA,
> > +		lpc32xx_sys_suspend_sz);
> > +	flush_cache_all();
> > +
> > +	/*
> > +	 * Copy code to suspend system into IRAM. The suspend code
> > +	 * needs to run from IRAM as DRAM may no longer be available
> > +	 * when the PLL is stopped.
> > +	 */
> > +	memcpy((void *) TEMP_IRAM_AREA, &lpc32xx_sys_suspend,
> > +		lpc32xx_sys_suspend_sz);
> 
> icache flush needed here? or does the above flush suffice? ... I
> believe you do need the flush.

It is not sufficient, and I'm not sure what that 'flush_cache_all'
above is doing there.

flush_icache_range() is always required after copying instructions
into a new kernel area prior to executing them to ensure that the
newly placed instructions are visible to instruction fetches.

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

* [PATCH 08/14] ARM: LPC32XX: Phytec 3250 platform support
  2010-02-12 20:08   ` Uwe Kleine-König
@ 2010-02-16 19:43     ` Kevin Wells
  0 siblings, 0 replies; 44+ messages in thread
From: Kevin Wells @ 2010-02-16 19:43 UTC (permalink / raw)
  To: linux-arm-kernel

> > +
> > +	gpio_request(LCD_POWER_GPIO, "LCD power");
> > +	gpio_direction_output(LCD_POWER_GPIO, 1);
> > +	gpio_request(BKL_POWER_GPIO, "LCD backlight power");
> > +	gpio_direction_output(BKL_POWER_GPIO, 1);
> I'd check the return values of the gpio_... functions.
> 

I'll get all the comments installed and get an updated set of
patches up this week.

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

* [PATCH 12/14] AMBA: CLCD: LPC32XX register swap in the clcd header file
  2010-02-12 16:41       ` Russell King - ARM Linux
@ 2010-02-16 20:27         ` Kevin Wells
  2010-02-18 17:21           ` Russell King - ARM Linux
  0 siblings, 1 reply; 44+ messages in thread
From: Kevin Wells @ 2010-02-16 20:27 UTC (permalink / raw)
  To: linux-arm-kernel



> > >
> > > On Mon, Feb 08, 2010 at 04:11:33PM -0800, wellsk40 at gmail.com wrote:
> > > > The CTRL and IENB registers need to be swapped for the LPC32XX
> > > > arch.
> > >
> > > Is your peripheral a PL110 or PL111 ?
> > >
> >
> > This part uses an unmodified PL111.
> 
> In which case, could you test this patch please:
> 
>     Video: ARM CLCD: Better fix for swapped IENB and CNTL registers
> 
>     On PL111, as found on Realview and other platforms, these registers
> are
>     always arranged as CNTL then IENB.  On PL110, these registers are IENB
>     then CNTL, except on Versatile platforms.
> 
>     Re-arrange the handling of these register swaps so that PL111 always
>     gets it right without resorting to ifdefs, leaving the only case
> needing
>     special handling being PL110 on Versatile.
> 
>     Fill out amba/clcd.h with the PL110/PL111 register definition
>     differences in case someone tries to use the PL110 specific
> definitions
>     on PL111.
> 
>     Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
> 

Patch tested and works fine on our PL111 hardware. Sorry, I have no
PL110 hardware to test it against.

>  drivers/video/amba-clcd.c |   31 ++++++++++++++++++++++++-------
>  include/linux/amba/clcd.h |   33 +++++++++++++++++----------------
>  2 files changed, 41 insertions(+), 23 deletions(-)
> 

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

* [PATCH 12/14] AMBA: CLCD: LPC32XX register swap in the clcd header file
  2010-02-16 20:27         ` Kevin Wells
@ 2010-02-18 17:21           ` Russell King - ARM Linux
  0 siblings, 0 replies; 44+ messages in thread
From: Russell King - ARM Linux @ 2010-02-18 17:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Feb 16, 2010 at 09:27:17PM +0100, Kevin Wells wrote:
> Patch tested and works fine on our PL111 hardware. Sorry, I have no
> PL110 hardware to test it against.

That's good enough; I'll queue it for this upcoming merge window.

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

* [PATCH 03/14] ARM: LPC32XX: Clock driver
  2010-02-09 10:39   ` Uwe Kleine-König
  2010-02-09 19:18     ` Kevin Wells
@ 2010-02-19  0:42     ` Kevin Wells
  2010-02-19  9:21       ` Uwe Kleine-König
  1 sibling, 1 reply; 44+ messages in thread
From: Kevin Wells @ 2010-02-19  0:42 UTC (permalink / raw)
  To: linux-arm-kernel

> > +
> > +static inline void clk_unlock(void)
> > +{
> > +	mutex_unlock(&clkm_lock);
> > +}
> > +
> > +static void local_clk_disable(struct clk *clk)
> > +{
> > +	/* Don't attempt to disable clock if it has no users */
> WARN_ON(clk->usecount <= 0)?

Is the expectation that the driver will always enable a clock
prior to disabling it and balance each disable with a previous
enable? I'm seeing a specific case of disable first, some
register accesses, and then clock enable on the amba clcd
driver (the warning fires on the first disable before enable).

[<c002b098>] (clk_disable+0x0/0x34) from [<c014555c>] (clcdfb_disable+0xa8/0xb0)
 r5:00000000 r4:c3c10400
[<c01454b4>] (clcdfb_disable+0x0/0xb0) from [<c014570c>] (clcdfb_set_par+0x50/0xe8)
 r6:00000028 r5:c3c10400 r4:c3c10400
[<c01456bc>] (clcdfb_set_par+0x0/0xe8) from [<c0140884>] (fbcon_init+0x2f4/0x42c)

> 
> > +	if (clk->usecount > 0) {
> > +		clk->usecount--;
> > +
> > +		/* Only disable clock when it has no more users */
> > +		if ((clk->usecount == 0) && (clk->enable))
> > +			clk->enable(clk, 0);
> > +
> > +		/* Check parent clocks, they may need to be disabled too */
> > +		if (clk->parent)
> > +			local_clk_disable(clk->parent);
> > +	}
> > +}
> > +

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

* [PATCH 03/14] ARM: LPC32XX: Clock driver
  2010-02-19  0:42     ` Kevin Wells
@ 2010-02-19  9:21       ` Uwe Kleine-König
  0 siblings, 0 replies; 44+ messages in thread
From: Uwe Kleine-König @ 2010-02-19  9:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Kevin,

On Fri, Feb 19, 2010 at 01:42:30AM +0100, Kevin Wells wrote:
> > > +
> > > +static inline void clk_unlock(void)
> > > +{
> > > +	mutex_unlock(&clkm_lock);
> > > +}
> > > +
> > > +static void local_clk_disable(struct clk *clk)
> > > +{
> > > +	/* Don't attempt to disable clock if it has no users */
> > WARN_ON(clk->usecount <= 0)?
> 
> Is the expectation that the driver will always enable a clock
> prior to disabling it and balance each disable with a previous
> enable?
Quoting include/linux/clk.h:

	 * Implementation detail: if the clock source is shared between
	 * multiple drivers, clk_enable() calls must be balanced by the
	 * same number of clk_disable() calls for the clock source to be
	 * disabled.
	 */

This doesn't answer your complete question, but yes, a driver that
havn't enabled a clk must not disable it.

>         I'm seeing a specific case of disable first, some
> register accesses, and then clock enable on the amba clcd
> driver (the warning fires on the first disable before enable).
> 
> [<c002b098>] (clk_disable+0x0/0x34) from [<c014555c>] (clcdfb_disable+0xa8/0xb0)
>  r5:00000000 r4:c3c10400
> [<c01454b4>] (clcdfb_disable+0x0/0xb0) from [<c014570c>] (clcdfb_set_par+0x50/0xe8)
>  r6:00000028 r5:c3c10400 r4:c3c10400
> [<c01456bc>] (clcdfb_set_par+0x0/0xe8) from [<c0140884>] (fbcon_init+0x2f4/0x42c)
So yes, this is a bug.

Best regards
Uwe

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

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

end of thread, other threads:[~2010-02-19  9:21 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-02-09  0:11 LPC32XX architecture files (updated v3) wellsk40 at gmail.com
2010-02-09  0:11 ` [PATCH 01/14] ARM: LPC32XX: Initial architecture header files wellsk40 at gmail.com
2010-02-09  9:31   ` Uwe Kleine-König
2010-02-09  9:52     ` Uwe Kleine-König
2010-02-09  9:59     ` Russell King - ARM Linux
2010-02-09 16:52       ` Uwe Kleine-König
2010-02-09 16:52         ` Uwe Kleine-König
2010-02-09 17:10         ` H Hartley Sweeten
2010-02-09 17:10           ` H Hartley Sweeten
2010-02-09 17:58         ` Russell King - ARM Linux
2010-02-09 17:58           ` Russell King - ARM Linux
2010-02-09 18:22         ` Josh Triplett
2010-02-09 19:17     ` Kevin Wells
2010-02-09  0:11 ` [PATCH 02/14] ARM: LPC32XX: Debug and IRQ macros wellsk40 at gmail.com
2010-02-09  9:45   ` Uwe Kleine-König
2010-02-09  0:11 ` [PATCH 03/14] ARM: LPC32XX: Clock driver wellsk40 at gmail.com
2010-02-09 10:39   ` Uwe Kleine-König
2010-02-09 19:18     ` Kevin Wells
2010-02-19  0:42     ` Kevin Wells
2010-02-19  9:21       ` Uwe Kleine-König
2010-02-09  0:11 ` [PATCH 04/14] ARM: LPC32XX: GPIO, timer, and IRQ drivers wellsk40 at gmail.com
2010-02-09 10:58   ` Uwe Kleine-König
2010-02-09  0:11 ` [PATCH 05/14] ARM: LPC32XX: System suspend support wellsk40 at gmail.com
2010-02-09 17:03   ` Uwe Kleine-König
2010-02-09 19:18     ` Kevin Wells
2010-02-14 16:51   ` Pavel Machek
2010-02-14 19:45     ` Russell King - ARM Linux
2010-02-09  0:11 ` [PATCH 06/14] ARM: LPC32XX: Serial support code wellsk40 at gmail.com
2010-02-09  0:11 ` [PATCH 07/14] ARM: LPC32XX: Misc support functions wellsk40 at gmail.com
2010-02-12 20:06   ` Uwe Kleine-König
2010-02-09  0:11 ` [PATCH 08/14] ARM: LPC32XX: Phytec 3250 platform support wellsk40 at gmail.com
2010-02-12 20:08   ` Uwe Kleine-König
2010-02-16 19:43     ` Kevin Wells
2010-02-09  0:11 ` [PATCH 09/14] ARM: LPC32XX: Arch config menu supoport and makefiles wellsk40 at gmail.com
2010-02-09  0:11 ` [PATCH 10/14] ARM: LPC32XX: Default PHY3250 kernel config (ramdisk) wellsk40 at gmail.com
2010-02-09  0:11 ` [PATCH 11/14] ARM: Add support for the LPC32XX arch wellsk40 at gmail.com
2010-02-09  0:11 ` [PATCH 12/14] AMBA: CLCD: LPC32XX register swap in the clcd header file wellsk40 at gmail.com
2010-02-12 14:31   ` Russell King - ARM Linux
2010-02-12 16:32     ` Kevin Wells
2010-02-12 16:41       ` Russell King - ARM Linux
2010-02-16 20:27         ` Kevin Wells
2010-02-18 17:21           ` Russell King - ARM Linux
2010-02-09  0:11 ` [PATCH 13/14] i2c: Add support for the LPC32XX arch wellsk40 at gmail.com
2010-02-09  0:11 ` [PATCH 14/14] WATCHDOG: " wellsk40 at gmail.com

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.