Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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