[PATCH v2 6/9] lpc2k: multifunction pin configuration

Kevin Wells kevin.wells at nxp.com
Fri Mar 18 13:42:43 EDT 2011


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

A small nit here..

You can replace this enum with a single macro, but it might be
a little easier all around to use the Px.y names for the GPIOs
instead of a just mapping the GPIO numbers linearly. This
follows the convention used in the LPC24XX User's guides,
EA schematics (at least 2468), and pin designations.

So..
MFP_PIN_GPIO0 maps to P0_0, MFP_PIN_GPIO32 maps to P1_0,
MFP_PIN_GPIO63 maps to P1_31, MFP_PIN_GPIO64 maps to P2_0, etc.

If this designation is used, you can see the mapping of a GPIO,
GPIO IRQ, or multi-function pin directly from the name and save
a little mental calculation converting the GPIOx numbers to Px_y
numbers when cross checking pin muxing and mapping.

This would affect GPIO_IRQ names, GPIOLIB names, and MFP names.
So something like..
> +#define GPIO0_RD1		MFP_CFG(GPIO0, AF1)
> +#define GPIO33_ENET_TXD1	MFP_CFG(GPIO33, AF1)
would be something like:
#define PGPIO(x, y)	(((x) * 32) + (y))
#define GPIO0_RD1		MFP_CFG(PGPIO(0, 0), AF1)
#define GPIO33_ENET_TXD1	MFP_CFG(PGPIO(1, 1), AF1)

Likewise, with IRQ number mapping, you could used a single macro
definition for both P0[0, 31] and P2[0, 31] ranges. It would help
save some space.

> +/* pin number; currently only 0-159 are used */
> +#define MFP_PIN(x)	((x) & 0x3ff)
> +
> +/* Alternate functions, currently only 0-3 are used */
> +#define MFP_AF0		(0x0 << 10)
> +#define MFP_AF1		(0x1 << 10)
> +#define MFP_AF2		(0x2 << 10)
> +#define MFP_AF3		(0x3 << 10)
> +#define MFP_AF_MASK	(0x3 << 10)
> +#define MFP_AF(x)	(((x) >> 10) & 0x3)
> +
> +/* Pullup/down configuration, currently only none/high/low are used */
> +#define MFP_PULL_NONE	(0x2 << 21)
> +#define MFP_PULL_LOW	(0x3 << 21)
> +#define MFP_PULL_HIGH	(0x0 << 21)
> +#define MFP_PULL_MASK	(0x3 << 21)
> +#define MFP_PULL(x)	(((x) >> 21) & 0x3)
> +
> +#define MFP_CFG_DEFAULT	(MFP_PULL_HIGH | MFP_AF0)
> +
> +#define MFP_CFG(pin, af)		\
> +	((MFP_CFG_DEFAULT & ~MFP_AF_MASK) |\
> +	 (MFP_PIN(MFP_PIN_##pin) | MFP_##af))
> +
> +#define MFP_CFG_PULL(pin, af, pull)	\
> +	((MFP_CFG_DEFAULT & ~(MFP_AF_MASK | MFP_PULL_MASK)) |\
> +	 (MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_##pull))
> +
> +#endif /* ARCH_LPC2K_MFP_H */
> diff --git a/arch/arm/mach-lpc2k/mfp.c b/arch/arm/mach-lpc2k/mfp.c
> new file mode 100644
> index 0000000..6e4779d
> --- /dev/null
> +++ b/arch/arm/mach-lpc2k/mfp.c
> @@ -0,0 +1,99 @@
> +/*
> + * Copyright (C) 2011 Team Embeded VOF
> + *     Ithamar R. Adema <ihamar.adema 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/io.h>
> +
> +#include <mach/hardware.h>
> +#include <mach/mfp.h>
> +
> +#define PINSEL(bank)	(0x00 + (bank)*4)
> +#define PINMODE(bank)	(0x40 + (bank)*4)
> +
> +struct gpio_desc {
> +	unsigned valid:1;
> +	unsigned long config;
> +};
> +
> +static struct gpio_desc gpio_desc[MFP_PIN_GPIO159 + 1];
> +
> +static int __mfp_config_gpio(unsigned gpio, unsigned long c)
> +{
> +	unsigned bank = gpio >> 4;
> +	unsigned shift = (gpio & 0xf) * 2;
> +	unsigned val;
> +
> +	/* Configure alternate function */
> +	val = __raw_readl(APB_PINSEL_BASE + PINSEL(bank));
> +	if ((val & (3 << shift)) &&
> +	    (val & (3 << shift)) != (MFP_AF(c) << shift))
> +		pr_warning
> +		    ("GPIO%d is already configured (%x), not reconfigured!\n",
> +		     gpio, (val & (3 << shift)) >> shift);
> +	else {
> +		val &= ~(0x3 << shift);
> +		val |= MFP_AF(c) << shift;
> +		__raw_writel(val, APB_PINSEL_BASE + PINSEL(bank));
> +	}
> +
> +	/* Configuration pullup/dn */
> +	val = __raw_readl(APB_PINSEL_BASE + PINMODE(bank));
> +	val &= ~(0x3 << shift);
> +	val |= MFP_PULL(c) << shift;
> +	__raw_writel(val, APB_PINSEL_BASE + PINMODE(bank));
> +
> +	return 0;
> +}
> +
> +static inline int __mfp_validate(int mfp)
> +{
> +	int gpio = mfp_to_gpio(mfp);
> +
> +	if (!gpio_desc[gpio].valid) {
> +		pr_warning("%s: GPIO%d is invalid pin\n", __func__, gpio);
> +		return -1;
> +	}
> +
> +	return gpio;
> +}
> +
> +void lpc2k_mfp_config(unsigned long *mfp_cfgs, int num)
> +{
> +	unsigned long flags;
> +	unsigned long *c;
> +	int i, gpio;
> +
> +	for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
> +
> +		gpio = __mfp_validate(MFP_PIN(*c));
> +		if (gpio < 0)
> +			continue;
> +
> +		local_irq_save(flags);
> +
> +		gpio_desc[gpio].config = *c;
> +		__mfp_config_gpio(gpio, *c);
> +
> +		local_irq_restore(flags);
> +	}
> +}
> +
> +static int __init lpc2k_mfp_init(void)
> +{
> +	int i;
> +
> +	for (i = MFP_PIN_GPIO0; i <= MFP_PIN_GPIO159; i++)
> +		gpio_desc[i].valid = 1;
> +
> +	return 0;
> +}
> +
> +postcore_initcall(lpc2k_mfp_init);
> --
> 1.7.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel



More information about the linux-arm-kernel mailing list