gpio.c (3829B)
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 19int __mcfgpio_get_value(unsigned gpio) 20{ 21 return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio); 22} 23EXPORT_SYMBOL(__mcfgpio_get_value); 24 25void __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} 48EXPORT_SYMBOL(__mcfgpio_set_value); 49 50int __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} 63EXPORT_SYMBOL(__mcfgpio_direction_input); 64 65int __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} 94EXPORT_SYMBOL(__mcfgpio_direction_output); 95 96int __mcfgpio_request(unsigned gpio) 97{ 98 return 0; 99} 100EXPORT_SYMBOL(__mcfgpio_request); 101 102void __mcfgpio_free(unsigned gpio) 103{ 104 __mcfgpio_direction_input(gpio); 105} 106EXPORT_SYMBOL(__mcfgpio_free); 107 108#ifdef CONFIG_GPIOLIB 109 110static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset) 111{ 112 return __mcfgpio_direction_input(offset); 113} 114 115static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset) 116{ 117 return !!__mcfgpio_get_value(offset); 118} 119 120static int mcfgpio_direction_output(struct gpio_chip *chip, unsigned offset, 121 int value) 122{ 123 return __mcfgpio_direction_output(offset, value); 124} 125 126static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset, 127 int value) 128{ 129 __mcfgpio_set_value(offset, value); 130} 131 132static int mcfgpio_request(struct gpio_chip *chip, unsigned offset) 133{ 134 return __mcfgpio_request(offset); 135} 136 137static void mcfgpio_free(struct gpio_chip *chip, unsigned offset) 138{ 139 __mcfgpio_free(offset); 140} 141 142static 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 154static 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 167static int __init mcfgpio_sysinit(void) 168{ 169 return gpiochip_add_data(&mcfgpio_chip, NULL); 170} 171 172core_initcall(mcfgpio_sysinit); 173#endif