^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Coldfire generic GPIO support.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/gpio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/coldfire.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/mcfsim.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/mcfgpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) int __mcfgpio_get_value(unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) EXPORT_SYMBOL(__mcfgpio_get_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) void __mcfgpio_set_value(unsigned gpio, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (gpio < MCFGPIO_SCR_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) MCFGPIO_PORTTYPE data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) data = mcfgpio_read(__mcfgpio_podr(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) data |= mcfgpio_bit(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) data &= ~mcfgpio_bit(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) mcfgpio_write(data, __mcfgpio_podr(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) mcfgpio_write(mcfgpio_bit(gpio),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MCFGPIO_SETR_PORT(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) mcfgpio_write(~mcfgpio_bit(gpio),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) MCFGPIO_CLRR_PORT(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) EXPORT_SYMBOL(__mcfgpio_set_value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int __mcfgpio_direction_input(unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) MCFGPIO_PORTTYPE dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) dir = mcfgpio_read(__mcfgpio_pddr(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) dir &= ~mcfgpio_bit(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) mcfgpio_write(dir, __mcfgpio_pddr(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) EXPORT_SYMBOL(__mcfgpio_direction_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int __mcfgpio_direction_output(unsigned gpio, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) MCFGPIO_PORTTYPE data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) data = mcfgpio_read(__mcfgpio_pddr(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) data |= mcfgpio_bit(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) mcfgpio_write(data, __mcfgpio_pddr(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /* now set the data to output */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (gpio < MCFGPIO_SCR_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) data = mcfgpio_read(__mcfgpio_podr(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) data |= mcfgpio_bit(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) data &= ~mcfgpio_bit(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) mcfgpio_write(data, __mcfgpio_podr(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) mcfgpio_write(mcfgpio_bit(gpio),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) MCFGPIO_SETR_PORT(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) mcfgpio_write(~mcfgpio_bit(gpio),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) MCFGPIO_CLRR_PORT(gpio));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) EXPORT_SYMBOL(__mcfgpio_direction_output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int __mcfgpio_request(unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) EXPORT_SYMBOL(__mcfgpio_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) void __mcfgpio_free(unsigned gpio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) __mcfgpio_direction_input(gpio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) EXPORT_SYMBOL(__mcfgpio_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #ifdef CONFIG_GPIOLIB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return __mcfgpio_direction_input(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return !!__mcfgpio_get_value(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static int mcfgpio_direction_output(struct gpio_chip *chip, unsigned offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return __mcfgpio_direction_output(offset, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) __mcfgpio_set_value(offset, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int mcfgpio_request(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return __mcfgpio_request(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static void mcfgpio_free(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) __mcfgpio_free(offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static int mcfgpio_to_irq(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #if defined(MCFGPIO_IRQ_MIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if ((offset >= MCFGPIO_IRQ_MIN) && (offset < MCFGPIO_IRQ_MAX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (offset < MCFGPIO_IRQ_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return MCFGPIO_IRQ_VECBASE + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) static struct gpio_chip mcfgpio_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .label = "mcfgpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) .request = mcfgpio_request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) .free = mcfgpio_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .direction_input = mcfgpio_direction_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) .direction_output = mcfgpio_direction_output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .get = mcfgpio_get_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .set = mcfgpio_set_value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) .to_irq = mcfgpio_to_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) .base = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) .ngpio = MCFGPIO_PIN_MAX,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static int __init mcfgpio_sysinit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return gpiochip_add_data(&mcfgpio_chip, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) core_initcall(mcfgpio_sysinit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #endif