/* * Coldfire generic GPIO support * * (C) Copyright 2009, Steven King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef coldfire_gpio_h #define coldfire_gpio_h #include #include #include #include /* * 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. * * This implementation attempts accomodate 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) /* 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) /* 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) /* * 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. */ #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 #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 /* * Coldfire specific helper functions */ /* return the port pin data register for a gpio */ static inline u32 __mcf_gpio_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) 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) 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 else return MCFGPIO_PPDR + mcfgpio_port(gpio - MCFGPIO_SCR_START); #endif } /* return the port output data register for a gpio */ static inline u32 __mcf_gpio_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) 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) 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 else return MCFGPIO_PODR + mcfgpio_port(gpio - MCFGPIO_SCR_START); #endif } /* * The Generic GPIO functions * * If the gpio is a compile time constant and is one of the Coldfire gpios, * use the inline version, otherwise dispatch thru gpiolib. */ static inline int gpio_get_value(unsigned gpio) { if (__builtin_constant_p(gpio) && gpio < MCFGPIO_PIN_MAX) return mcfgpio_read(__mcf_gpio_ppdr(gpio)) & mcfgpio_bit(gpio); else return __gpio_get_value(gpio); } static inline void gpio_set_value(unsigned gpio, int value) { if (__builtin_constant_p(gpio) && gpio < MCFGPIO_PIN_MAX) { if (gpio < MCFGPIO_SCR_START) { unsigned long flags; MCFGPIO_PORTTYPE data; local_irq_save(flags); data = mcfgpio_read(__mcf_gpio_podr(gpio)); if (value) data |= mcfgpio_bit(gpio); else data &= ~mcfgpio_bit(gpio); mcfgpio_write(data, __mcf_gpio_podr(gpio)); local_irq_restore(flags); } else { if (value) mcfgpio_write(mcfgpio_bit(gpio), MCFGPIO_SETR_PORT(gpio)); else mcfgpio_write(~mcfgpio_bit(gpio), MCFGPIO_CLRR_PORT(gpio)); } } else __gpio_set_value(gpio, value); } static inline int gpio_to_irq(unsigned gpio) { return (gpio < MCFGPIO_IRQ_MAX) ? gpio + MCFGPIO_IRQ_VECBASE : -EINVAL; } static inline int irq_to_gpio(unsigned irq) { return (irq >= MCFGPIO_IRQ_VECBASE && irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) ? irq - MCFGPIO_IRQ_VECBASE : -ENXIO; } static inline int gpio_cansleep(unsigned gpio) { return gpio < MCFGPIO_PIN_MAX ? 0 : __gpio_cansleep(gpio); } #endif