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