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