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 coldfire_gpio_h
98c2ecf20Sopenharmony_ci#define coldfire_gpio_h
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/io.h>
128c2ecf20Sopenharmony_ci#include <asm/coldfire.h>
138c2ecf20Sopenharmony_ci#include <asm/mcfsim.h>
148c2ecf20Sopenharmony_ci#include <asm/mcfgpio.h>
158c2ecf20Sopenharmony_ci/*
168c2ecf20Sopenharmony_ci * The Generic GPIO functions
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci * If the gpio is a compile time constant and is one of the Coldfire gpios,
198c2ecf20Sopenharmony_ci * use the inline version, otherwise dispatch thru gpiolib.
208c2ecf20Sopenharmony_ci */
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic inline int gpio_get_value(unsigned gpio)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	if (__builtin_constant_p(gpio) && gpio < MCFGPIO_PIN_MAX)
258c2ecf20Sopenharmony_ci		return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio);
268c2ecf20Sopenharmony_ci	else
278c2ecf20Sopenharmony_ci		return __gpio_get_value(gpio);
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic inline void gpio_set_value(unsigned gpio, int value)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	if (__builtin_constant_p(gpio) && gpio < MCFGPIO_PIN_MAX) {
338c2ecf20Sopenharmony_ci		if (gpio < MCFGPIO_SCR_START) {
348c2ecf20Sopenharmony_ci			unsigned long flags;
358c2ecf20Sopenharmony_ci			MCFGPIO_PORTTYPE data;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci			local_irq_save(flags);
388c2ecf20Sopenharmony_ci			data = mcfgpio_read(__mcfgpio_podr(gpio));
398c2ecf20Sopenharmony_ci			if (value)
408c2ecf20Sopenharmony_ci				data |= mcfgpio_bit(gpio);
418c2ecf20Sopenharmony_ci			else
428c2ecf20Sopenharmony_ci				data &= ~mcfgpio_bit(gpio);
438c2ecf20Sopenharmony_ci			mcfgpio_write(data, __mcfgpio_podr(gpio));
448c2ecf20Sopenharmony_ci			local_irq_restore(flags);
458c2ecf20Sopenharmony_ci		} else {
468c2ecf20Sopenharmony_ci			if (value)
478c2ecf20Sopenharmony_ci				mcfgpio_write(mcfgpio_bit(gpio),
488c2ecf20Sopenharmony_ci						MCFGPIO_SETR_PORT(gpio));
498c2ecf20Sopenharmony_ci			else
508c2ecf20Sopenharmony_ci				mcfgpio_write(~mcfgpio_bit(gpio),
518c2ecf20Sopenharmony_ci						MCFGPIO_CLRR_PORT(gpio));
528c2ecf20Sopenharmony_ci		}
538c2ecf20Sopenharmony_ci	} else
548c2ecf20Sopenharmony_ci		__gpio_set_value(gpio, value);
558c2ecf20Sopenharmony_ci}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistatic inline int gpio_to_irq(unsigned gpio)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci#if defined(MCFGPIO_IRQ_MIN)
608c2ecf20Sopenharmony_ci	if ((gpio >= MCFGPIO_IRQ_MIN) && (gpio < MCFGPIO_IRQ_MAX))
618c2ecf20Sopenharmony_ci#else
628c2ecf20Sopenharmony_ci	if (gpio < MCFGPIO_IRQ_MAX)
638c2ecf20Sopenharmony_ci#endif
648c2ecf20Sopenharmony_ci		return gpio + MCFGPIO_IRQ_VECBASE;
658c2ecf20Sopenharmony_ci	else
668c2ecf20Sopenharmony_ci		return __gpio_to_irq(gpio);
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic inline int irq_to_gpio(unsigned irq)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	return (irq >= MCFGPIO_IRQ_VECBASE &&
728c2ecf20Sopenharmony_ci		irq < (MCFGPIO_IRQ_VECBASE + MCFGPIO_IRQ_MAX)) ?
738c2ecf20Sopenharmony_ci		irq - MCFGPIO_IRQ_VECBASE : -ENXIO;
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistatic inline int gpio_cansleep(unsigned gpio)
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	return gpio < MCFGPIO_PIN_MAX ? 0 : __gpio_cansleep(gpio);
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci#ifndef CONFIG_GPIOLIB
828c2ecf20Sopenharmony_cistatic inline int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	int err;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	err = gpio_request(gpio, label);
878c2ecf20Sopenharmony_ci	if (err)
888c2ecf20Sopenharmony_ci		return err;
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	if (flags & GPIOF_DIR_IN)
918c2ecf20Sopenharmony_ci		err = gpio_direction_input(gpio);
928c2ecf20Sopenharmony_ci	else
938c2ecf20Sopenharmony_ci		err = gpio_direction_output(gpio,
948c2ecf20Sopenharmony_ci			(flags & GPIOF_INIT_HIGH) ? 1 : 0);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	if (err)
978c2ecf20Sopenharmony_ci		gpio_free(gpio);
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	return err;
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci#endif /* !CONFIG_GPIOLIB */
1028c2ecf20Sopenharmony_ci#endif
103