[PATCH v3 6/9] lpc2k: multifunction pin configuration
Ithamar R. Adema
ithamar.adema at team-embedded.nl
Sun Mar 20 16:30:06 EDT 2011
Inspired by the mfp support in PXA. Includes definition of pins
for NXP LPC2468/78.
Signed-off-by: Ithamar R. Adema <ithamar.adema at team-embedded.nl>
---
changes since v2:
* Removed MFP_PIN_* enum.
* Renamed GPIOx_signal defines to Px_y_signal.
no changes since v1.
---
arch/arm/mach-lpc2k/Makefile | 2 +-
arch/arm/mach-lpc2k/include/mach/hardware.h | 1 +
arch/arm/mach-lpc2k/include/mach/mfp-lpc24xx.h | 98 +++++++++++++++++++++++
arch/arm/mach-lpc2k/include/mach/mfp.h | 43 ++++++++++
arch/arm/mach-lpc2k/mfp.c | 100 ++++++++++++++++++++++++
5 files changed, 243 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-lpc2k/include/mach/mfp-lpc24xx.h
create mode 100644 arch/arm/mach-lpc2k/include/mach/mfp.h
create mode 100644 arch/arm/mach-lpc2k/mfp.c
diff --git a/arch/arm/mach-lpc2k/Makefile b/arch/arm/mach-lpc2k/Makefile
index 89596a7..2c50bb9 100644
--- a/arch/arm/mach-lpc2k/Makefile
+++ b/arch/arm/mach-lpc2k/Makefile
@@ -1 +1 @@
-obj-y := clock.o irq.o gpio.o time.o
+obj-y := clock.o irq.o gpio.o mfp.o time.o
diff --git a/arch/arm/mach-lpc2k/include/mach/hardware.h b/arch/arm/mach-lpc2k/include/mach/hardware.h
index b8c471b..1a20126 100644
--- a/arch/arm/mach-lpc2k/include/mach/hardware.h
+++ b/arch/arm/mach-lpc2k/include/mach/hardware.h
@@ -21,6 +21,7 @@
#define APB_TIMER1_BASE 0xe0008000
#define APB_UART0_BASE 0xe000c000
#define APB_GPIO_BASE 0xe0028000
+#define APB_PINSEL_BASE 0xe002c000
#define APB_SCB_BASE 0xe01fc000
#define APH_VIC_BASE 0xfffff000
diff --git a/arch/arm/mach-lpc2k/include/mach/mfp-lpc24xx.h b/arch/arm/mach-lpc2k/include/mach/mfp-lpc24xx.h
new file mode 100644
index 0000000..dafb8f1
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/mfp-lpc24xx.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema at team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MACH_LPC2K_MFP_LPC24XX_H
+#define MACH_LPC2K_MFP_LPC24XX_H
+
+#include <mach/mfp.h>
+
+#define P0_0_RD1 MFP_CFG(LPC2K_GPIO(0,0), AF1)
+#define P0_0_TXD3 MFP_CFG(LPC2K_GPIO(0,0), AF2)
+#define P0_0_SDA1 MFP_CFG(LPC2K_GPIO(0,0), AF3)
+#define P0_1_TD1 MFP_CFG(LPC2K_GPIO(0,1), AF1)
+#define P0_1_RXD3 MFP_CFG(LPC2K_GPIO(0,1), AF2)
+#define P0_1_SCL1 MFP_CFG(LPC2K_GPIO(0,1), AF3)
+#define P0_2_TXD0 MFP_CFG(LPC2K_GPIO(0,2), AF1)
+#define P0_3_RXD0 MFP_CFG(LPC2K_GPIO(0,3), AF1)
+#define P0_4_LCDVD0 MFP_CFG(LPC2K_GPIO(0,4), AF1)
+#define P0_5_LCDVD1 MFP_CFG(LPC2K_GPIO(0,5), AF1)
+#define P0_6_LCDVD8 MFP_CFG(LPC2K_GPIO(0,6), AF1)
+#define P0_7_LCDVD9 MFP_CFG(LPC2K_GPIO(0,7), AF1)
+#define P0_8_LCDVD16 MFP_CFG(LPC2K_GPIO(0,8), AF1)
+#define P0_9_LCDVD17 MFP_CFG(LPC2K_GPIO(0,9), AF1)
+#define P0_10_TXD2 MFP_CFG(LPC2K_GPIO(0,10), AF1)
+#define P0_11_RXD2 MFP_CFG(LPC2K_GPIO(0,11), AF1)
+#define P0_12_USB_PPWR2 MFP_CFG(LPC2K_GPIO(0,12), AF1)
+#define P0_13_USB_UP_LED2 MFP_CFG(LPC2K_GPIO(0,13), AF1)
+#define P0_15_SCK MFP_CFG(LPC2K_GPIO(0,15), AF3)
+#define P0_17_MISO MFP_CFG(LPC2K_GPIO(0,17), AF3)
+#define P0_18_MOSI MFP_CFG(LPC2K_GPIO(0,18), AF3)
+#define P0_27_SDA0 MFP_CFG(LPC2K_GPIO(0,27), AF1)
+#define P0_28_SCL0 MFP_CFG(LPC2K_GPIO(0,28), AF1)
+#define P0_29_USB_Dp1 MFP_CFG(LPC2K_GPIO(0,29), AF1)
+#define P0_30_USB_Dn1 MFP_CFG(LPC2K_GPIO(0,30), AF1)
+#define P0_31_USB_Dp2 MFP_CFG(LPC2K_GPIO(0,31), AF1)
+#define P1_0_ENET_TXD0 MFP_CFG(LPC2K_GPIO(1,0), AF1)
+#define P1_1_ENET_TXD1 MFP_CFG(LPC2K_GPIO(1,1), AF1)
+#define P1_2_MCICLK MFP_CFG(LPC2K_GPIO(1,2), AF2)
+#define P1_3_MCICMD MFP_CFG(LPC2K_GPIO(1,3), AF2)
+#define P1_4_ENET_TX_EN MFP_CFG(LPC2K_GPIO(1,4), AF1)
+#define P1_5_MCIPWR MFP_CFG(LPC2K_GPIO(1,5), AF2)
+#define P1_6_ENET_TX_CLK MFP_CFG(LPC2K_GPIO(1,6), AF1)
+#define P1_6_MCIDAT0 MFP_CFG(LPC2K_GPIO(1,6), AF2)
+#define P1_7_MCIDAT1 MFP_CFG(LPC2K_GPIO(1,7), AF2)
+#define P1_8_ENET_CRS MFP_CFG(LPC2K_GPIO(1,8), AF1)
+#define P1_9_ENET_RXD0 MFP_CFG(LPC2K_GPIO(1,9), AF1)
+#define P1_10_ENET_RXD1 MFP_CFG(LPC2K_GPIO(1,10), AF1)
+#define P1_11_MCIDAT2 MFP_CFG(LPC2K_GPIO(1,11), AF2)
+#define P1_12_MCIDAT3 MFP_CFG(LPC2K_GPIO(1,12), AF2)
+#define P1_14_ENET_RX_ERR MFP_CFG(LPC2K_GPIO(1,14), AF1)
+#define P1_15_ENET_REF_CLK MFP_CFG(LPC2K_GPIO(1,15), AF1)
+#define P1_16_ENET_MDC MFP_CFG(LPC2K_GPIO(1,16), AF1)
+#define P1_17_ENET_MDIO MFP_CFG(LPC2K_GPIO(1,17), AF1)
+#define P1_18_PWM1 MFP_CFG(LPC2K_GPIO(1,18), AF2)
+#define P1_20_LCDVD10 MFP_CFG(LPC2K_GPIO(1,20), AF1)
+#define P1_21_LCDVD11 MFP_CFG(LPC2K_GPIO(1,21), AF1)
+#define P1_22_LCDVD12 MFP_CFG(LPC2K_GPIO(1,22), AF1)
+#define P1_23_LCDVD13 MFP_CFG(LPC2K_GPIO(1,23), AF1)
+#define P1_24_LCDVD14 MFP_CFG(LPC2K_GPIO(1,24), AF1)
+#define P1_25_LCDVD15 MFP_CFG(LPC2K_GPIO(1,25), AF1)
+#define P1_26_LCDVD20 MFP_CFG(LPC2K_GPIO(1,26), AF1)
+#define P1_27_LCDVD21 MFP_CFG(LPC2K_GPIO(1,27), AF1)
+#define P1_28_LCDVD22 MFP_CFG(LPC2K_GPIO(1,28), AF1)
+#define P1_29_LCDVD23 MFP_CFG(LPC2K_GPIO(1,29), AF1)
+#define P1_30_VBUS MFP_CFG(LPC2K_GPIO(1,30), AF2)
+#define P1_31_USB_OVRCR2 MFP_CFG(LPC2K_GPIO(1,31), AF1)
+#define P2_0_LCDPWR MFP_CFG(LPC2K_GPIO(2,0), AF3)
+#define P2_1_LCDLE MFP_CFG(LPC2K_GPIO(2,1), AF3)
+#define P2_2_LCDDCLK MFP_CFG(LPC2K_GPIO(2,2), AF3)
+#define P2_3_LCDFP MFP_CFG(LPC2K_GPIO(2,3), AF3)
+#define P2_4_LCDM MFP_CFG(LPC2K_GPIO(2,4), AF3)
+#define P2_5_LCDLP MFP_CFG(LPC2K_GPIO(2,5), AF3)
+#define P2_6_LCDVP4 MFP_CFG(LPC2K_GPIO(2,6), AF3)
+#define P2_7_LCDVP5 MFP_CFG(LPC2K_GPIO(2,7), AF3)
+#define P2_8_LCDVP6 MFP_CFG(LPC2K_GPIO(2,8), AF3)
+#define P2_9_LCDVP7 MFP_CFG(LPC2K_GPIO(2,9), AF3)
+#define P2_11_LCDCLKIN MFP_CFG(LPC2K_GPIO(2,11), AF1)
+#define P2_12_LCDVP18 MFP_CFG(LPC2K_GPIO(2,12), AF1)
+#define P2_13_LCDVP19 MFP_CFG(LPC2K_GPIO(2,13), AF1)
+#define P3_16_TXD1 MFP_CFG(LPC2K_GPIO(3,16), AF3)
+#define P3_17_RXD1 MFP_CFG(LPC2K_GPIO(3,17), AF3)
+#define P3_18_CTS1 MFP_CFG(LPC2K_GPIO(3,18), AF3)
+#define P3_19_DCD1 MFP_CFG(LPC2K_GPIO(3,19), AF3)
+#define P3_20_DSR1 MFP_CFG(LPC2K_GPIO(3,20), AF3)
+#define P3_21_DR1 MFP_CFG(LPC2K_GPIO(3,21), AF3)
+#define P3_22_RI1 MFP_CFG(LPC2K_GPIO(3,22), AF3)
+#define P3_30_RTS1 MFP_CFG(LPC2K_GPIO(3,30), AF3)
+#define P4_28_TXD3 MFP_CFG(LPC2K_GPIO(4,28), AF3)
+#define P4_28_LCDVP2 MFP_CFG(LPC2K_GPIO(4,28), AF2)
+#define P4_29_RXD3 MFP_CFG(LPC2K_GPIO(4,29), AF3)
+#define P4_29_LCDVP3 MFP_CFG(LPC2K_GPIO(4,29), AF2)
+
+#endif /* MACH_LPC2K_MFP_LPC24XX_H */
diff --git a/arch/arm/mach-lpc2k/include/mach/mfp.h b/arch/arm/mach-lpc2k/include/mach/mfp.h
new file mode 100644
index 0000000..c3d0378
--- /dev/null
+++ b/arch/arm/mach-lpc2k/include/mach/mfp.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 Team Embedded VOF
+ * Ithamar R. Adema <ihamar.adema at team-embedded.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef ARCH_LPC2K_MFP_H
+#define ARCH_LPC2K_MFP_H
+
+#define mfp_to_gpio(m) ((m) % 160)
+
+/* pin number; currently only 0-159 are used */
+#define MFP_PIN(x) ((x) & 0x3ff)
+
+/* Alternate functions, currently only 0-3 are used */
+#define MFP_AF0 (0x0 << 10)
+#define MFP_AF1 (0x1 << 10)
+#define MFP_AF2 (0x2 << 10)
+#define MFP_AF3 (0x3 << 10)
+#define MFP_AF_MASK (0x3 << 10)
+#define MFP_AF(x) (((x) >> 10) & 0x3)
+
+/* Pullup/down configuration, currently only none/high/low are used */
+#define MFP_PULL_NONE (0x2 << 21)
+#define MFP_PULL_LOW (0x3 << 21)
+#define MFP_PULL_HIGH (0x0 << 21)
+#define MFP_PULL_MASK (0x3 << 21)
+#define MFP_PULL(x) (((x) >> 21) & 0x3)
+
+#define MFP_CFG_DEFAULT (MFP_PULL_HIGH | MFP_AF0)
+
+#define MFP_CFG(pin, af) \
+ ((MFP_CFG_DEFAULT & ~MFP_AF_MASK) |\
+ (MFP_PIN(pin) | MFP_##af))
+
+#define MFP_CFG_PULL(pin, af, pull) \
+ ((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_PULL_MASK)) |\
+ (MFP_PIN(pin) | MFP_##af | MFP_##pull))
+
+#endif /* ARCH_LPC2K_MFP_H */
diff --git a/arch/arm/mach-lpc2k/mfp.c b/arch/arm/mach-lpc2k/mfp.c
new file mode 100644
index 0000000..c0d356b
--- /dev/null
+++ b/arch/arm/mach-lpc2k/mfp.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2011 Team Embeded VOF
+ * Ithamar R. Adema <ihamar.adema at team-embedded.nl>
+ *
+ * Based on MFP code from mach-pxa.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mfp.h>
+
+#define PINSEL(bank) (0x00 + (bank)*4)
+#define PINMODE(bank) (0x40 + (bank)*4)
+
+struct gpio_desc {
+ unsigned valid:1;
+ unsigned long config;
+};
+
+static struct gpio_desc gpio_desc[LPC2K_GPIO(4,31) + 1];
+
+static int __mfp_config_gpio(unsigned gpio, unsigned long c)
+{
+ unsigned bank = gpio >> 4;
+ unsigned shift = (gpio & 0xf) * 2;
+ unsigned val;
+
+ /* Configure alternate function */
+ val = __raw_readl(APB_PINSEL_BASE + PINSEL(bank));
+ if ((val & (3 << shift)) &&
+ (val & (3 << shift)) != (MFP_AF(c) << shift))
+ pr_warning
+ ("GPIO%d is already configured (%x), not reconfigured!\n",
+ gpio, (val & (3 << shift)) >> shift);
+ else {
+ val &= ~(0x3 << shift);
+ val |= MFP_AF(c) << shift;
+ __raw_writel(val, APB_PINSEL_BASE + PINSEL(bank));
+ }
+
+ /* Configuration pullup/dn */
+ val = __raw_readl(APB_PINSEL_BASE + PINMODE(bank));
+ val &= ~(0x3 << shift);
+ val |= MFP_PULL(c) << shift;
+ __raw_writel(val, APB_PINSEL_BASE + PINMODE(bank));
+
+ return 0;
+}
+
+static inline int __mfp_validate(int mfp)
+{
+ int gpio = mfp_to_gpio(mfp);
+
+ if (!gpio_desc[gpio].valid) {
+ pr_warning("%s: GPIO%d is invalid pin\n", __func__, gpio);
+ return -1;
+ }
+
+ return gpio;
+}
+
+void lpc2k_mfp_config(unsigned long *mfp_cfgs, int num)
+{
+ unsigned long flags;
+ unsigned long *c;
+ int i, gpio;
+
+ for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
+
+ gpio = __mfp_validate(MFP_PIN(*c));
+ if (gpio < 0)
+ continue;
+
+ local_irq_save(flags);
+
+ gpio_desc[gpio].config = *c;
+ __mfp_config_gpio(gpio, *c);
+
+ local_irq_restore(flags);
+ }
+}
+
+static int __init lpc2k_mfp_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(gpio_desc); i++)
+ gpio_desc[i].valid = 1;
+
+ return 0;
+}
+
+postcore_initcall(lpc2k_mfp_init);
--
1.7.1
More information about the linux-arm-kernel
mailing list