diff options
Diffstat (limited to 'arch/m68k/include/asm/mcfgpio.h')
| -rw-r--r-- | arch/m68k/include/asm/mcfgpio.h | 339 | 
1 files changed, 273 insertions, 66 deletions
diff --git a/arch/m68k/include/asm/mcfgpio.h b/arch/m68k/include/asm/mcfgpio.h index fe468eaa51e..fa1059f50df 100644 --- a/arch/m68k/include/asm/mcfgpio.h +++ b/arch/m68k/include/asm/mcfgpio.h @@ -16,82 +16,289 @@  #ifndef mcfgpio_h  #define mcfgpio_h -#include <linux/io.h> +#ifdef CONFIG_GPIOLIB  #include <asm-generic/gpio.h> +#else -struct mcf_gpio_chip { -	struct gpio_chip gpio_chip; -	void __iomem *pddr; -	void __iomem *podr; -	void __iomem *ppdr; -	void __iomem *setr; -	void __iomem *clrr; -	const u8 *gpio_to_pinmux; -}; +int __mcfgpio_get_value(unsigned gpio); +void __mcfgpio_set_value(unsigned gpio, int value); +int __mcfgpio_direction_input(unsigned gpio); +int __mcfgpio_direction_output(unsigned gpio, int value); +int __mcfgpio_request(unsigned gpio); +void __mcfgpio_free(unsigned gpio); -extern struct mcf_gpio_chip mcf_gpio_chips[]; -extern unsigned int mcf_gpio_chips_size; +/* our alternate 'gpiolib' functions */ +static inline int __gpio_get_value(unsigned gpio) +{ +	if (gpio < MCFGPIO_PIN_MAX) +		return __mcfgpio_get_value(gpio); +	else +		return -EINVAL; +} + +static inline void __gpio_set_value(unsigned gpio, int value) +{ +	if (gpio < MCFGPIO_PIN_MAX) +		__mcfgpio_set_value(gpio, value); +} + +static inline int __gpio_cansleep(unsigned gpio) +{ +	if (gpio < MCFGPIO_PIN_MAX) +		return 0; +	else +		return -EINVAL; +} + +static inline int __gpio_to_irq(unsigned gpio) +{ +	return -EINVAL; +} + +static inline int gpio_direction_input(unsigned gpio) +{ +	if (gpio < MCFGPIO_PIN_MAX) +		return __mcfgpio_direction_input(gpio); +	else +		return -EINVAL; +} + +static inline int gpio_direction_output(unsigned gpio, int value) +{ +	if (gpio < MCFGPIO_PIN_MAX) +		return __mcfgpio_direction_output(gpio, value); +	else +		return -EINVAL; +} + +static inline int gpio_request(unsigned gpio, const char *label) +{ +	if (gpio < MCFGPIO_PIN_MAX) +		return __mcfgpio_request(gpio); +	else +		return -EINVAL; +} + +static inline void gpio_free(unsigned gpio) +{ +	if (gpio < MCFGPIO_PIN_MAX) +		__mcfgpio_free(gpio); +} + +#endif /* CONFIG_GPIOLIB */ -int mcf_gpio_direction_input(struct gpio_chip *, unsigned); -int mcf_gpio_get_value(struct gpio_chip *, unsigned); -int mcf_gpio_direction_output(struct gpio_chip *, unsigned, int); -void mcf_gpio_set_value(struct gpio_chip *, unsigned, int); -void mcf_gpio_set_value_fast(struct gpio_chip *, unsigned, int); -int mcf_gpio_request(struct gpio_chip *, unsigned); -void mcf_gpio_free(struct gpio_chip *, unsigned);  /* - *	Define macros to ease the pain of setting up the GPIO tables. There - *	are two cases we need to deal with here, they cover all currently - *	available ColdFire GPIO hardware. There are of course minor differences - *	in the layout and number of bits in each ColdFire part, but the macros - *	take all that in. + * The Freescale Coldfire family is quite varied in how they implement GPIO. + * Some parts have 8 bit ports, some have 16bit and some have 32bit; some have + * only one port, others have multiple ports; some have a single data latch + * for both input and output, others have a separate pin data register to read + * input; some require a read-modify-write access to change an output, others + * have set and clear registers for some of the outputs; Some have all the + * GPIOs in a single control area, others have some GPIOs implemented in + * different modules.   * - *	Firstly is the conventional GPIO registers where we toggle individual - *	bits in a register, preserving the other bits in the register. For - *	lack of a better term I have called this the slow method. + * This implementation attempts accommodate the differences while presenting + * a generic interface that will optimize to as few instructions as possible. + */ +#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \ +    defined(CONFIG_M520x) || defined(CONFIG_M523x) || \ +    defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ +    defined(CONFIG_M532x) || defined(CONFIG_M54xx) || \ +    defined(CONFIG_M5441x) + +/* These parts have GPIO organized by 8 bit ports */ + +#define MCFGPIO_PORTTYPE		u8 +#define MCFGPIO_PORTSIZE		8 +#define mcfgpio_read(port)		__raw_readb(port) +#define mcfgpio_write(data, port)	__raw_writeb(data, port) + +#elif defined(CONFIG_M5307) || defined(CONFIG_M5407) || defined(CONFIG_M5272) + +/* These parts have GPIO organized by 16 bit ports */ + +#define MCFGPIO_PORTTYPE		u16 +#define MCFGPIO_PORTSIZE		16 +#define mcfgpio_read(port)		__raw_readw(port) +#define mcfgpio_write(data, port)	__raw_writew(data, port) + +#elif defined(CONFIG_M5249) || defined(CONFIG_M525x) + +/* These parts have GPIO organized by 32 bit ports */ + +#define MCFGPIO_PORTTYPE		u32 +#define MCFGPIO_PORTSIZE		32 +#define mcfgpio_read(port)		__raw_readl(port) +#define mcfgpio_write(data, port)	__raw_writel(data, port) + +#endif + +#define mcfgpio_bit(gpio)		(1 << ((gpio) %  MCFGPIO_PORTSIZE)) +#define mcfgpio_port(gpio)		((gpio) / MCFGPIO_PORTSIZE) + +#if defined(CONFIG_M520x) || defined(CONFIG_M523x) || \ +    defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ +    defined(CONFIG_M532x) || defined(CONFIG_M5441x) +/* + * These parts have an 'Edge' Port module (external interrupt/GPIO) which uses + * read-modify-write to change an output and a GPIO module which has separate + * set/clr registers to directly change outputs with a single write access.   */ -#define	MCFGPS(mlabel, mbase, mngpio, mpddr, mpodr, mppdr)		    \ -	{								    \ -		.gpio_chip			= {			    \ -			.label			= #mlabel,		    \ -			.request		= mcf_gpio_request,	    \ -			.free			= mcf_gpio_free,	    \ -			.direction_input	= mcf_gpio_direction_input, \ -			.direction_output	= mcf_gpio_direction_output,\ -			.get			= mcf_gpio_get_value,	    \ -			.set			= mcf_gpio_set_value,       \ -			.base			= mbase,		    \ -			.ngpio			= mngpio,		    \ -		},							    \ -		.pddr		= (void __iomem *) mpddr,		    \ -		.podr		= (void __iomem *) mpodr,		    \ -		.ppdr		= (void __iomem *) mppdr,		    \ -	} +#if defined(CONFIG_M528x) +/* + * The 528x also has GPIOs in other modules (GPT, QADC) which use + * read-modify-write as well as those controlled by the EPORT and GPIO modules. + */ +#define MCFGPIO_SCR_START		40 +#elif defined(CONFIGM5441x) +/* The m5441x EPORT doesn't have its own GPIO port, uses PORT C */ +#define MCFGPIO_SCR_START		0 +#else +#define MCFGPIO_SCR_START		8 +#endif + +#define MCFGPIO_SETR_PORT(gpio)		(MCFGPIO_SETR + \ +					mcfgpio_port(gpio - MCFGPIO_SCR_START)) +#define MCFGPIO_CLRR_PORT(gpio)		(MCFGPIO_CLRR + \ +					mcfgpio_port(gpio - MCFGPIO_SCR_START)) +#else + +#define MCFGPIO_SCR_START		MCFGPIO_PIN_MAX +/* with MCFGPIO_SCR == MCFGPIO_PIN_MAX, these will be optimized away */ +#define MCFGPIO_SETR_PORT(gpio)		0 +#define MCFGPIO_CLRR_PORT(gpio)		0 + +#endif  /* - *	Secondly is the faster case, where we have set and clear registers - *	that allow us to set or clear a bit with a single write, not having - *	to worry about preserving other bits. + * Coldfire specific helper functions   */ -#define	MCFGPF(mlabel, mbase, mngpio)					    \ -	{								    \ -		.gpio_chip			= {			    \ -			.label			= #mlabel,		    \ -			.request		= mcf_gpio_request,	    \ -			.free			= mcf_gpio_free,	    \ -			.direction_input	= mcf_gpio_direction_input, \ -			.direction_output	= mcf_gpio_direction_output,\ -			.get			= mcf_gpio_get_value,	    \ -			.set			= mcf_gpio_set_value_fast,  \ -			.base			= mbase,		    \ -			.ngpio			= mngpio,		    \ -		},							    \ -		.pddr		= (void __iomem *) MCFGPIO_PDDR_##mlabel,   \ -		.podr		= (void __iomem *) MCFGPIO_PODR_##mlabel,   \ -		.ppdr		= (void __iomem *) MCFGPIO_PPDSDR_##mlabel, \ -		.setr		= (void __iomem *) MCFGPIO_PPDSDR_##mlabel, \ -		.clrr		= (void __iomem *) MCFGPIO_PCLRR_##mlabel,  \ -	} +/* return the port pin data register for a gpio */ +static inline u32 __mcfgpio_ppdr(unsigned gpio) +{ +#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \ +    defined(CONFIG_M5307) || defined(CONFIG_M5407) +	return MCFSIM_PADAT; +#elif defined(CONFIG_M5272) +	if (gpio < 16) +		return MCFSIM_PADAT; +	else if (gpio < 32) +		return MCFSIM_PBDAT; +	else +		return MCFSIM_PCDAT; +#elif defined(CONFIG_M5249) || defined(CONFIG_M525x) +	if (gpio < 32) +		return MCFSIM2_GPIOREAD; +	else +		return MCFSIM2_GPIO1READ; +#elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \ +      defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ +      defined(CONFIG_M532x) || defined(CONFIG_M5441x) +#if !defined(CONFIG_M5441x) +	if (gpio < 8) +		return MCFEPORT_EPPDR; +#if defined(CONFIG_M528x) +	else if (gpio < 16) +		return MCFGPTA_GPTPORT; +	else if (gpio < 24) +		return MCFGPTB_GPTPORT; +	else if (gpio < 32) +		return MCFQADC_PORTQA; +	else if (gpio < 40) +		return MCFQADC_PORTQB; +#endif /* defined(CONFIG_M528x) */ +	else +#endif /* !defined(CONFIG_M5441x) */ +		return MCFGPIO_PPDR + mcfgpio_port(gpio - MCFGPIO_SCR_START); +#else +	return 0; +#endif +} + +/* return the port output data register for a gpio */ +static inline u32 __mcfgpio_podr(unsigned gpio) +{ +#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \ +    defined(CONFIG_M5307) || defined(CONFIG_M5407) +	return MCFSIM_PADAT; +#elif defined(CONFIG_M5272) +	if (gpio < 16) +		return MCFSIM_PADAT; +	else if (gpio < 32) +		return MCFSIM_PBDAT; +	else +		return MCFSIM_PCDAT; +#elif defined(CONFIG_M5249) || defined(CONFIG_M525x) +	if (gpio < 32) +		return MCFSIM2_GPIOWRITE; +	else +		return MCFSIM2_GPIO1WRITE; +#elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \ +      defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ +      defined(CONFIG_M532x) || defined(CONFIG_M5441x) +#if !defined(CONFIG_M5441x) +	if (gpio < 8) +		return MCFEPORT_EPDR; +#if defined(CONFIG_M528x) +	else if (gpio < 16) +		return MCFGPTA_GPTPORT; +	else if (gpio < 24) +		return MCFGPTB_GPTPORT; +	else if (gpio < 32) +		return MCFQADC_PORTQA; +	else if (gpio < 40) +		return MCFQADC_PORTQB; +#endif /* defined(CONFIG_M528x) */ +	else +#endif /* !defined(CONFIG_M5441x) */ +		return MCFGPIO_PODR + mcfgpio_port(gpio - MCFGPIO_SCR_START); +#else +	return 0; +#endif +} + +/* return the port direction data register for a gpio */ +static inline u32 __mcfgpio_pddr(unsigned gpio) +{ +#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \ +    defined(CONFIG_M5307) || defined(CONFIG_M5407) +	return MCFSIM_PADDR; +#elif defined(CONFIG_M5272) +	if (gpio < 16) +		return MCFSIM_PADDR; +	else if (gpio < 32) +		return MCFSIM_PBDDR; +	else +		return MCFSIM_PCDDR; +#elif defined(CONFIG_M5249) || defined(CONFIG_M525x) +	if (gpio < 32) +		return MCFSIM2_GPIOENABLE; +	else +		return MCFSIM2_GPIO1ENABLE; +#elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \ +      defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ +      defined(CONFIG_M532x) || defined(CONFIG_M5441x) +#if !defined(CONFIG_M5441x) +	if (gpio < 8) +		return MCFEPORT_EPDDR; +#if defined(CONFIG_M528x) +	else if (gpio < 16) +		return MCFGPTA_GPTDDR; +	else if (gpio < 24) +		return MCFGPTB_GPTDDR; +	else if (gpio < 32) +		return MCFQADC_DDRQA; +	else if (gpio < 40) +		return MCFQADC_DDRQB; +#endif /* defined(CONFIG_M528x) */ +	else +#endif /* !defined(CONFIG_M5441x) */ +		return MCFGPIO_PDDR + mcfgpio_port(gpio - MCFGPIO_SCR_START); +#else +	return 0;  #endif +} + +#endif /* mcfgpio_h */  |