1/* 2 * arch/arm/mach-ns9xxx/gpio.c 3 * 4 * Copyright (C) 2006,2007 by Digi International Inc. 5 * All rights reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published by 9 * the Free Software Foundation. 10 */ 11#include <linux/kernel.h> 12#include <linux/compiler.h> 13#include <linux/init.h> 14#include <linux/spinlock.h> 15#include <linux/module.h> 16#include <linux/bitops.h> 17 18#include <mach/gpio.h> 19#include <mach/processor.h> 20#include <mach/processor-ns9360.h> 21#include <asm/bug.h> 22#include <asm/types.h> 23 24#include "gpio-ns9360.h" 25 26#if defined(CONFIG_PROCESSOR_NS9360) 27#define GPIO_MAX 72 28#elif defined(CONFIG_PROCESSOR_NS9750) 29#define GPIO_MAX 49 30#endif 31 32/* protects BBU_GCONFx and BBU_GCTRLx */ 33static spinlock_t gpio_lock = __SPIN_LOCK_UNLOCKED(gpio_lock); 34 35/* only access gpiores with atomic ops */ 36static DECLARE_BITMAP(gpiores, GPIO_MAX + 1); 37 38static inline int ns9xxx_valid_gpio(unsigned gpio) 39{ 40#if defined(CONFIG_PROCESSOR_NS9360) 41 if (processor_is_ns9360()) 42 return gpio <= 72; 43 else 44#endif 45#if defined(CONFIG_PROCESSOR_NS9750) 46 if (processor_is_ns9750()) 47 return gpio <= 49; 48 else 49#endif 50 { 51 BUG(); 52 return 0; 53 } 54} 55 56int gpio_request(unsigned gpio, const char *label) 57{ 58 if (likely(ns9xxx_valid_gpio(gpio))) 59 return test_and_set_bit(gpio, gpiores) ? -EBUSY : 0; 60 else 61 return -EINVAL; 62} 63EXPORT_SYMBOL(gpio_request); 64 65void gpio_free(unsigned gpio) 66{ 67 might_sleep(); 68 clear_bit(gpio, gpiores); 69 return; 70} 71EXPORT_SYMBOL(gpio_free); 72 73int gpio_direction_input(unsigned gpio) 74{ 75 if (likely(ns9xxx_valid_gpio(gpio))) { 76 int ret = -EINVAL; 77 unsigned long flags; 78 79 spin_lock_irqsave(&gpio_lock, flags); 80#if defined(CONFIG_PROCESSOR_NS9360) 81 if (processor_is_ns9360()) 82 ret = __ns9360_gpio_configure(gpio, 0, 0, 3); 83 else 84#endif 85 BUG(); 86 87 spin_unlock_irqrestore(&gpio_lock, flags); 88 89 return ret; 90 91 } else 92 return -EINVAL; 93} 94EXPORT_SYMBOL(gpio_direction_input); 95 96int gpio_direction_output(unsigned gpio, int value) 97{ 98 if (likely(ns9xxx_valid_gpio(gpio))) { 99 int ret = -EINVAL; 100 unsigned long flags; 101 102 gpio_set_value(gpio, value); 103 104 spin_lock_irqsave(&gpio_lock, flags); 105#if defined(CONFIG_PROCESSOR_NS9360) 106 if (processor_is_ns9360()) 107 ret = __ns9360_gpio_configure(gpio, 1, 0, 3); 108 else 109#endif 110 BUG(); 111 112 spin_unlock_irqrestore(&gpio_lock, flags); 113 114 return ret; 115 } else 116 return -EINVAL; 117} 118EXPORT_SYMBOL(gpio_direction_output); 119 120int gpio_get_value(unsigned gpio) 121{ 122#if defined(CONFIG_PROCESSOR_NS9360) 123 if (processor_is_ns9360()) 124 return ns9360_gpio_get_value(gpio); 125 else 126#endif 127 { 128 BUG(); 129 return -EINVAL; 130 } 131} 132EXPORT_SYMBOL(gpio_get_value); 133 134void gpio_set_value(unsigned gpio, int value) 135{ 136 unsigned long flags; 137 spin_lock_irqsave(&gpio_lock, flags); 138#if defined(CONFIG_PROCESSOR_NS9360) 139 if (processor_is_ns9360()) 140 ns9360_gpio_set_value(gpio, value); 141 else 142#endif 143 BUG(); 144 145 spin_unlock_irqrestore(&gpio_lock, flags); 146} 147EXPORT_SYMBOL(gpio_set_value); 148