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