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 bus_type mcfgpio_subsys = { 162 .name = "gpio", 163 .dev_name = "gpio", 164}; 165 166static struct gpio_chip mcfgpio_chip = { 167 .label = "mcfgpio", 168 .request = mcfgpio_request, 169 .free = mcfgpio_free, 170 .direction_input = mcfgpio_direction_input, 171 .direction_output = mcfgpio_direction_output, 172 .get = mcfgpio_get_value, 173 .set = mcfgpio_set_value, 174 .to_irq = mcfgpio_to_irq, 175 .base = 0, 176 .ngpio = MCFGPIO_PIN_MAX, 177}; 178 179static int __init mcfgpio_sysinit(void) 180{ 181 gpiochip_add(&mcfgpio_chip); 182 return subsys_system_register(&mcfgpio_subsys, NULL); 183} 184 185core_initcall(mcfgpio_sysinit); 186#endif 187