18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Coldfire generic GPIO support.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifndef mcfgpio_h
98c2ecf20Sopenharmony_ci#define mcfgpio_h
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#ifdef CONFIG_GPIOLIB
128c2ecf20Sopenharmony_ci#include <asm-generic/gpio.h>
138c2ecf20Sopenharmony_ci#else
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ciint __mcfgpio_get_value(unsigned gpio);
168c2ecf20Sopenharmony_civoid __mcfgpio_set_value(unsigned gpio, int value);
178c2ecf20Sopenharmony_ciint __mcfgpio_direction_input(unsigned gpio);
188c2ecf20Sopenharmony_ciint __mcfgpio_direction_output(unsigned gpio, int value);
198c2ecf20Sopenharmony_ciint __mcfgpio_request(unsigned gpio);
208c2ecf20Sopenharmony_civoid __mcfgpio_free(unsigned gpio);
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* our alternate 'gpiolib' functions */
238c2ecf20Sopenharmony_cistatic inline int __gpio_get_value(unsigned gpio)
248c2ecf20Sopenharmony_ci{
258c2ecf20Sopenharmony_ci	if (gpio < MCFGPIO_PIN_MAX)
268c2ecf20Sopenharmony_ci		return __mcfgpio_get_value(gpio);
278c2ecf20Sopenharmony_ci	else
288c2ecf20Sopenharmony_ci		return -EINVAL;
298c2ecf20Sopenharmony_ci}
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic inline void __gpio_set_value(unsigned gpio, int value)
328c2ecf20Sopenharmony_ci{
338c2ecf20Sopenharmony_ci	if (gpio < MCFGPIO_PIN_MAX)
348c2ecf20Sopenharmony_ci		__mcfgpio_set_value(gpio, value);
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic inline int __gpio_cansleep(unsigned gpio)
388c2ecf20Sopenharmony_ci{
398c2ecf20Sopenharmony_ci	if (gpio < MCFGPIO_PIN_MAX)
408c2ecf20Sopenharmony_ci		return 0;
418c2ecf20Sopenharmony_ci	else
428c2ecf20Sopenharmony_ci		return -EINVAL;
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic inline int __gpio_to_irq(unsigned gpio)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	return -EINVAL;
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic inline int gpio_direction_input(unsigned gpio)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	if (gpio < MCFGPIO_PIN_MAX)
538c2ecf20Sopenharmony_ci		return __mcfgpio_direction_input(gpio);
548c2ecf20Sopenharmony_ci	else
558c2ecf20Sopenharmony_ci		return -EINVAL;
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic inline int gpio_direction_output(unsigned gpio, int value)
598c2ecf20Sopenharmony_ci{
608c2ecf20Sopenharmony_ci	if (gpio < MCFGPIO_PIN_MAX)
618c2ecf20Sopenharmony_ci		return __mcfgpio_direction_output(gpio, value);
628c2ecf20Sopenharmony_ci	else
638c2ecf20Sopenharmony_ci		return -EINVAL;
648c2ecf20Sopenharmony_ci}
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_cistatic inline int gpio_request(unsigned gpio, const char *label)
678c2ecf20Sopenharmony_ci{
688c2ecf20Sopenharmony_ci	if (gpio < MCFGPIO_PIN_MAX)
698c2ecf20Sopenharmony_ci		return __mcfgpio_request(gpio);
708c2ecf20Sopenharmony_ci	else
718c2ecf20Sopenharmony_ci		return -EINVAL;
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic inline void gpio_free(unsigned gpio)
758c2ecf20Sopenharmony_ci{
768c2ecf20Sopenharmony_ci	if (gpio < MCFGPIO_PIN_MAX)
778c2ecf20Sopenharmony_ci		__mcfgpio_free(gpio);
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci#endif /* CONFIG_GPIOLIB */
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci/*
848c2ecf20Sopenharmony_ci * The Freescale Coldfire family is quite varied in how they implement GPIO.
858c2ecf20Sopenharmony_ci * Some parts have 8 bit ports, some have 16bit and some have 32bit; some have
868c2ecf20Sopenharmony_ci * only one port, others have multiple ports; some have a single data latch
878c2ecf20Sopenharmony_ci * for both input and output, others have a separate pin data register to read
888c2ecf20Sopenharmony_ci * input; some require a read-modify-write access to change an output, others
898c2ecf20Sopenharmony_ci * have set and clear registers for some of the outputs; Some have all the
908c2ecf20Sopenharmony_ci * GPIOs in a single control area, others have some GPIOs implemented in
918c2ecf20Sopenharmony_ci * different modules.
928c2ecf20Sopenharmony_ci *
938c2ecf20Sopenharmony_ci * This implementation attempts accommodate the differences while presenting
948c2ecf20Sopenharmony_ci * a generic interface that will optimize to as few instructions as possible.
958c2ecf20Sopenharmony_ci */
968c2ecf20Sopenharmony_ci#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
978c2ecf20Sopenharmony_ci    defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
988c2ecf20Sopenharmony_ci    defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
998c2ecf20Sopenharmony_ci    defined(CONFIG_M53xx) || defined(CONFIG_M54xx) || \
1008c2ecf20Sopenharmony_ci    defined(CONFIG_M5441x)
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci/* These parts have GPIO organized by 8 bit ports */
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci#define MCFGPIO_PORTTYPE		u8
1058c2ecf20Sopenharmony_ci#define MCFGPIO_PORTSIZE		8
1068c2ecf20Sopenharmony_ci#define mcfgpio_read(port)		__raw_readb(port)
1078c2ecf20Sopenharmony_ci#define mcfgpio_write(data, port)	__raw_writeb(data, port)
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci#elif defined(CONFIG_M5307) || defined(CONFIG_M5407) || defined(CONFIG_M5272)
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci/* These parts have GPIO organized by 16 bit ports */
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci#define MCFGPIO_PORTTYPE		u16
1148c2ecf20Sopenharmony_ci#define MCFGPIO_PORTSIZE		16
1158c2ecf20Sopenharmony_ci#define mcfgpio_read(port)		__raw_readw(port)
1168c2ecf20Sopenharmony_ci#define mcfgpio_write(data, port)	__raw_writew(data, port)
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci#elif defined(CONFIG_M5249) || defined(CONFIG_M525x)
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci/* These parts have GPIO organized by 32 bit ports */
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci#define MCFGPIO_PORTTYPE		u32
1238c2ecf20Sopenharmony_ci#define MCFGPIO_PORTSIZE		32
1248c2ecf20Sopenharmony_ci#define mcfgpio_read(port)		__raw_readl(port)
1258c2ecf20Sopenharmony_ci#define mcfgpio_write(data, port)	__raw_writel(data, port)
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci#endif
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci#define mcfgpio_bit(gpio)		(1 << ((gpio) %  MCFGPIO_PORTSIZE))
1308c2ecf20Sopenharmony_ci#define mcfgpio_port(gpio)		((gpio) / MCFGPIO_PORTSIZE)
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci#if defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
1338c2ecf20Sopenharmony_ci    defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
1348c2ecf20Sopenharmony_ci    defined(CONFIG_M53xx) || defined(CONFIG_M54xx) || \
1358c2ecf20Sopenharmony_ci    defined(CONFIG_M5441x)
1368c2ecf20Sopenharmony_ci/*
1378c2ecf20Sopenharmony_ci * These parts have an 'Edge' Port module (external interrupt/GPIO) which uses
1388c2ecf20Sopenharmony_ci * read-modify-write to change an output and a GPIO module which has separate
1398c2ecf20Sopenharmony_ci * set/clr registers to directly change outputs with a single write access.
1408c2ecf20Sopenharmony_ci */
1418c2ecf20Sopenharmony_ci#if defined(CONFIG_M528x)
1428c2ecf20Sopenharmony_ci/*
1438c2ecf20Sopenharmony_ci * The 528x also has GPIOs in other modules (GPT, QADC) which use
1448c2ecf20Sopenharmony_ci * read-modify-write as well as those controlled by the EPORT and GPIO modules.
1458c2ecf20Sopenharmony_ci */
1468c2ecf20Sopenharmony_ci#define MCFGPIO_SCR_START		40
1478c2ecf20Sopenharmony_ci#elif defined(CONFIGM5441x)
1488c2ecf20Sopenharmony_ci/* The m5441x EPORT doesn't have its own GPIO port, uses PORT C */
1498c2ecf20Sopenharmony_ci#define MCFGPIO_SCR_START		0
1508c2ecf20Sopenharmony_ci#else
1518c2ecf20Sopenharmony_ci#define MCFGPIO_SCR_START		8
1528c2ecf20Sopenharmony_ci#endif
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci#define MCFGPIO_SETR_PORT(gpio)		(MCFGPIO_SETR + \
1558c2ecf20Sopenharmony_ci					mcfgpio_port(gpio - MCFGPIO_SCR_START))
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci#define MCFGPIO_CLRR_PORT(gpio)		(MCFGPIO_CLRR + \
1588c2ecf20Sopenharmony_ci					mcfgpio_port(gpio - MCFGPIO_SCR_START))
1598c2ecf20Sopenharmony_ci#else
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci#define MCFGPIO_SCR_START		MCFGPIO_PIN_MAX
1628c2ecf20Sopenharmony_ci/* with MCFGPIO_SCR == MCFGPIO_PIN_MAX, these will be optimized away */
1638c2ecf20Sopenharmony_ci#define MCFGPIO_SETR_PORT(gpio)		0
1648c2ecf20Sopenharmony_ci#define MCFGPIO_CLRR_PORT(gpio)		0
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci#endif
1678c2ecf20Sopenharmony_ci/*
1688c2ecf20Sopenharmony_ci * Coldfire specific helper functions
1698c2ecf20Sopenharmony_ci */
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci/* return the port pin data register for a gpio */
1728c2ecf20Sopenharmony_cistatic inline u32 __mcfgpio_ppdr(unsigned gpio)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
1758c2ecf20Sopenharmony_ci    defined(CONFIG_M5307) || defined(CONFIG_M5407)
1768c2ecf20Sopenharmony_ci	return MCFSIM_PADAT;
1778c2ecf20Sopenharmony_ci#elif defined(CONFIG_M5272)
1788c2ecf20Sopenharmony_ci	if (gpio < 16)
1798c2ecf20Sopenharmony_ci		return MCFSIM_PADAT;
1808c2ecf20Sopenharmony_ci	else if (gpio < 32)
1818c2ecf20Sopenharmony_ci		return MCFSIM_PBDAT;
1828c2ecf20Sopenharmony_ci	else
1838c2ecf20Sopenharmony_ci		return MCFSIM_PCDAT;
1848c2ecf20Sopenharmony_ci#elif defined(CONFIG_M5249) || defined(CONFIG_M525x)
1858c2ecf20Sopenharmony_ci	if (gpio < 32)
1868c2ecf20Sopenharmony_ci		return MCFSIM2_GPIOREAD;
1878c2ecf20Sopenharmony_ci	else
1888c2ecf20Sopenharmony_ci		return MCFSIM2_GPIO1READ;
1898c2ecf20Sopenharmony_ci#elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
1908c2ecf20Sopenharmony_ci      defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
1918c2ecf20Sopenharmony_ci      defined(CONFIG_M53xx) || defined(CONFIG_M54xx) || \
1928c2ecf20Sopenharmony_ci      defined(CONFIG_M5441x)
1938c2ecf20Sopenharmony_ci#if !defined(CONFIG_M5441x)
1948c2ecf20Sopenharmony_ci	if (gpio < 8)
1958c2ecf20Sopenharmony_ci		return MCFEPORT_EPPDR;
1968c2ecf20Sopenharmony_ci#if defined(CONFIG_M528x)
1978c2ecf20Sopenharmony_ci	else if (gpio < 16)
1988c2ecf20Sopenharmony_ci		return MCFGPTA_GPTPORT;
1998c2ecf20Sopenharmony_ci	else if (gpio < 24)
2008c2ecf20Sopenharmony_ci		return MCFGPTB_GPTPORT;
2018c2ecf20Sopenharmony_ci	else if (gpio < 32)
2028c2ecf20Sopenharmony_ci		return MCFQADC_PORTQA;
2038c2ecf20Sopenharmony_ci	else if (gpio < 40)
2048c2ecf20Sopenharmony_ci		return MCFQADC_PORTQB;
2058c2ecf20Sopenharmony_ci#endif /* defined(CONFIG_M528x) */
2068c2ecf20Sopenharmony_ci	else
2078c2ecf20Sopenharmony_ci#endif /* !defined(CONFIG_M5441x) */
2088c2ecf20Sopenharmony_ci		return MCFGPIO_PPDR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
2098c2ecf20Sopenharmony_ci#else
2108c2ecf20Sopenharmony_ci	return 0;
2118c2ecf20Sopenharmony_ci#endif
2128c2ecf20Sopenharmony_ci}
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci/* return the port output data register for a gpio */
2158c2ecf20Sopenharmony_cistatic inline u32 __mcfgpio_podr(unsigned gpio)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
2188c2ecf20Sopenharmony_ci    defined(CONFIG_M5307) || defined(CONFIG_M5407)
2198c2ecf20Sopenharmony_ci	return MCFSIM_PADAT;
2208c2ecf20Sopenharmony_ci#elif defined(CONFIG_M5272)
2218c2ecf20Sopenharmony_ci	if (gpio < 16)
2228c2ecf20Sopenharmony_ci		return MCFSIM_PADAT;
2238c2ecf20Sopenharmony_ci	else if (gpio < 32)
2248c2ecf20Sopenharmony_ci		return MCFSIM_PBDAT;
2258c2ecf20Sopenharmony_ci	else
2268c2ecf20Sopenharmony_ci		return MCFSIM_PCDAT;
2278c2ecf20Sopenharmony_ci#elif defined(CONFIG_M5249) || defined(CONFIG_M525x)
2288c2ecf20Sopenharmony_ci	if (gpio < 32)
2298c2ecf20Sopenharmony_ci		return MCFSIM2_GPIOWRITE;
2308c2ecf20Sopenharmony_ci	else
2318c2ecf20Sopenharmony_ci		return MCFSIM2_GPIO1WRITE;
2328c2ecf20Sopenharmony_ci#elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
2338c2ecf20Sopenharmony_ci      defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
2348c2ecf20Sopenharmony_ci      defined(CONFIG_M53xx) || defined(CONFIG_M54xx) || \
2358c2ecf20Sopenharmony_ci      defined(CONFIG_M5441x)
2368c2ecf20Sopenharmony_ci#if !defined(CONFIG_M5441x)
2378c2ecf20Sopenharmony_ci	if (gpio < 8)
2388c2ecf20Sopenharmony_ci		return MCFEPORT_EPDR;
2398c2ecf20Sopenharmony_ci#if defined(CONFIG_M528x)
2408c2ecf20Sopenharmony_ci	else if (gpio < 16)
2418c2ecf20Sopenharmony_ci		return MCFGPTA_GPTPORT;
2428c2ecf20Sopenharmony_ci	else if (gpio < 24)
2438c2ecf20Sopenharmony_ci		return MCFGPTB_GPTPORT;
2448c2ecf20Sopenharmony_ci	else if (gpio < 32)
2458c2ecf20Sopenharmony_ci		return MCFQADC_PORTQA;
2468c2ecf20Sopenharmony_ci	else if (gpio < 40)
2478c2ecf20Sopenharmony_ci		return MCFQADC_PORTQB;
2488c2ecf20Sopenharmony_ci#endif /* defined(CONFIG_M528x) */
2498c2ecf20Sopenharmony_ci	else
2508c2ecf20Sopenharmony_ci#endif /* !defined(CONFIG_M5441x) */
2518c2ecf20Sopenharmony_ci		return MCFGPIO_PODR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
2528c2ecf20Sopenharmony_ci#else
2538c2ecf20Sopenharmony_ci	return 0;
2548c2ecf20Sopenharmony_ci#endif
2558c2ecf20Sopenharmony_ci}
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci/* return the port direction data register for a gpio */
2588c2ecf20Sopenharmony_cistatic inline u32 __mcfgpio_pddr(unsigned gpio)
2598c2ecf20Sopenharmony_ci{
2608c2ecf20Sopenharmony_ci#if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
2618c2ecf20Sopenharmony_ci    defined(CONFIG_M5307) || defined(CONFIG_M5407)
2628c2ecf20Sopenharmony_ci	return MCFSIM_PADDR;
2638c2ecf20Sopenharmony_ci#elif defined(CONFIG_M5272)
2648c2ecf20Sopenharmony_ci	if (gpio < 16)
2658c2ecf20Sopenharmony_ci		return MCFSIM_PADDR;
2668c2ecf20Sopenharmony_ci	else if (gpio < 32)
2678c2ecf20Sopenharmony_ci		return MCFSIM_PBDDR;
2688c2ecf20Sopenharmony_ci	else
2698c2ecf20Sopenharmony_ci		return MCFSIM_PCDDR;
2708c2ecf20Sopenharmony_ci#elif defined(CONFIG_M5249) || defined(CONFIG_M525x)
2718c2ecf20Sopenharmony_ci	if (gpio < 32)
2728c2ecf20Sopenharmony_ci		return MCFSIM2_GPIOENABLE;
2738c2ecf20Sopenharmony_ci	else
2748c2ecf20Sopenharmony_ci		return MCFSIM2_GPIO1ENABLE;
2758c2ecf20Sopenharmony_ci#elif defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
2768c2ecf20Sopenharmony_ci      defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
2778c2ecf20Sopenharmony_ci      defined(CONFIG_M53xx) || defined(CONFIG_M54xx) || \
2788c2ecf20Sopenharmony_ci      defined(CONFIG_M5441x)
2798c2ecf20Sopenharmony_ci#if !defined(CONFIG_M5441x)
2808c2ecf20Sopenharmony_ci	if (gpio < 8)
2818c2ecf20Sopenharmony_ci		return MCFEPORT_EPDDR;
2828c2ecf20Sopenharmony_ci#if defined(CONFIG_M528x)
2838c2ecf20Sopenharmony_ci	else if (gpio < 16)
2848c2ecf20Sopenharmony_ci		return MCFGPTA_GPTDDR;
2858c2ecf20Sopenharmony_ci	else if (gpio < 24)
2868c2ecf20Sopenharmony_ci		return MCFGPTB_GPTDDR;
2878c2ecf20Sopenharmony_ci	else if (gpio < 32)
2888c2ecf20Sopenharmony_ci		return MCFQADC_DDRQA;
2898c2ecf20Sopenharmony_ci	else if (gpio < 40)
2908c2ecf20Sopenharmony_ci		return MCFQADC_DDRQB;
2918c2ecf20Sopenharmony_ci#endif /* defined(CONFIG_M528x) */
2928c2ecf20Sopenharmony_ci	else
2938c2ecf20Sopenharmony_ci#endif /* !defined(CONFIG_M5441x) */
2948c2ecf20Sopenharmony_ci		return MCFGPIO_PDDR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
2958c2ecf20Sopenharmony_ci#else
2968c2ecf20Sopenharmony_ci	return 0;
2978c2ecf20Sopenharmony_ci#endif
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci#endif /* mcfgpio_h */
301