1/* 2 * Generic GPIO 3 * 4 * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $Id: gen_gpio.c,v 1.1 2009-10-30 20:51:47 $ 19 */ 20 21 22#include <linux/module.h> 23#include <linux/init.h> 24#include <linux/spinlock.h> 25#include <linux/gpio.h> 26 27#include <typedefs.h> 28#include <bcmutils.h> 29#include <siutils.h> 30#include <bcmdevs.h> 31 32#define BCM947XX_GENGPIO_DEBUG 0 33#if BCM947XX_GENGPIO_DEBUG 34//#define DBG(x...) printk(KERN_DEBUG x) 35#define DBG(x...) printk(KERN_ERR x) 36#else 37#define DBG(x...) 38#endif 39 40/* Global SB handle */ 41extern si_t *bcm947xx_sih; 42 43/* Convenience */ 44#define gpio_sih bcm947xx_sih 45//static si_t *gpio_sih; 46int mask; 47 48#ifndef GPIO_COMMON_SPINLOCK_NAME 49#define GPIO_COMMON_SPINLOCK_NAME lock 50static DEFINE_SPINLOCK(GPIO_COMMON_SPINLOCK_NAME); 51#else 52DEFINE_SPINLOCK(GPIO_COMMON_SPINLOCK_NAME); 53EXPORT_SYMBOL(GPIO_COMMON_SPINLOCK_NAME); 54#endif 55 56#ifdef CONFIG_GPIOLIB 57# define BCM5301X_GPIO_FUNCNAME(func) bcm5301x_##func 58# define BCM5301X_GPIO_FUNCDECL(func) static BCM5301X_GPIO_FUNCNAME(func) 59# define BCM5301X_GPIO_EXPORT(func) 60#else 61# define BCM5301X_GPIO_FUNCDECL(func) func 62# define BCM5301X_GPIO_EXPORT(func) EXPORT_SYMBOL(func) 63#endif 64 65int BCM5301X_GPIO_FUNCDECL(gpio_direction_input)(unsigned gpio) 66{ 67 int ret; 68 unsigned long flags; 69 70 spin_lock_irqsave(&GPIO_COMMON_SPINLOCK_NAME, flags); 71 ret = si_gpioouten(gpio_sih, (1<<gpio), 0, GPIO_APP_PRIORITY); 72 spin_unlock_irqrestore(&GPIO_COMMON_SPINLOCK_NAME, flags); 73 74 DBG("%s: gpio %d - input 0x%x\n", __FUNCTION__, gpio, ret); 75 return 0; 76} 77BCM5301X_GPIO_EXPORT(gpio_direction_input); 78 79int BCM5301X_GPIO_FUNCDECL(gpio_direction_output)(unsigned gpio, int value) 80{ 81 int out, outen; 82 unsigned long flags; 83 84 spin_lock_irqsave(&GPIO_COMMON_SPINLOCK_NAME, flags); 85 outen = si_gpioouten(gpio_sih, (1<<gpio), (1<<gpio), GPIO_APP_PRIORITY); 86 out = si_gpioout(gpio_sih, (1<<gpio), (value ? (1<<gpio) : 0), GPIO_APP_PRIORITY); 87 spin_unlock_irqrestore(&GPIO_COMMON_SPINLOCK_NAME, flags); 88 89 DBG("%s: gpio %d, value %d - out 0x%x outen 0x%x\n", __FUNCTION__, gpio, value, out, outen); 90 return 0; 91} 92BCM5301X_GPIO_EXPORT(gpio_direction_output); 93 94int gpio_get_value(unsigned int gpio) 95{ 96 uint32 get; 97 unsigned long flags; 98 99 spin_lock_irqsave(&GPIO_COMMON_SPINLOCK_NAME, flags); 100 get = si_gpioin(gpio_sih); 101 get &= (1<<gpio); 102 spin_unlock_irqrestore(&GPIO_COMMON_SPINLOCK_NAME, flags); 103 104 return (get ? 1 : 0); 105} 106EXPORT_SYMBOL(gpio_get_value); 107 108void gpio_set_value(unsigned int gpio, int value) 109{ 110 unsigned long flags; 111 112 spin_lock_irqsave(&GPIO_COMMON_SPINLOCK_NAME, flags); 113 si_gpioout(gpio_sih, (1<<gpio), (value ? (1<<gpio) : 0), GPIO_APP_PRIORITY); 114 spin_unlock_irqrestore(&GPIO_COMMON_SPINLOCK_NAME, flags); 115} 116EXPORT_SYMBOL(gpio_set_value); 117 118int BCM5301X_GPIO_FUNCDECL(gpio_request)(unsigned int gpio, const char *label) 119{ 120 int ret; 121 unsigned long flags; 122 123 spin_lock_irqsave(&GPIO_COMMON_SPINLOCK_NAME, flags); 124 125 mask |= (1<<gpio); 126 127 ret = si_gpioreserve(gpio_sih, (1<<gpio), GPIO_APP_PRIORITY); 128 DBG("%s: gpio %d label %s mask 0x%x reserve 0x%x\n", __FUNCTION__, gpio, 129 label, mask, ret); 130 131 ret = si_gpiocontrol(gpio_sih, (1<<gpio), 0, GPIO_APP_PRIORITY); 132 DBG("%s: si_gpiocontrol 0x%x\n", __FUNCTION__, ret); 133 134 /* clear pulldown */ 135 ret = si_gpiopull(gpio_sih, GPIO_PULLDN, (1<<gpio), 0); 136 DBG("%s: si_gpiopull (down) 0x%x\n", __FUNCTION__, ret); 137 /* Set pullup */ 138 ret = si_gpiopull(gpio_sih, GPIO_PULLUP, (1<<gpio), (1<<gpio)); 139 DBG("%s: si_gpiopull (up) 0x%x\n", __FUNCTION__, ret); 140 141 spin_unlock_irqrestore(&GPIO_COMMON_SPINLOCK_NAME, flags); 142 143 return 0; 144} 145BCM5301X_GPIO_EXPORT(gpio_request); 146 147void BCM5301X_GPIO_FUNCDECL(gpio_free)(unsigned int gpio) 148{ 149 unsigned long flags; 150 151 spin_lock_irqsave(&GPIO_COMMON_SPINLOCK_NAME, flags); 152 153 mask &= ~(1<<gpio); 154 155 /* clear pullup */ 156 si_gpiopull(gpio_sih, GPIO_PULLUP, (1<<gpio), 0); 157 si_gpiorelease(gpio_sih, (1<<gpio), GPIO_APP_PRIORITY); 158 159 spin_unlock_irqrestore(&GPIO_COMMON_SPINLOCK_NAME, flags); 160 161 DBG("%s: gpio %d mask 0x%x\n", __FUNCTION__, gpio, mask); 162} 163BCM5301X_GPIO_EXPORT(gpio_free); 164 165#ifdef CONFIG_GPIOLIB 166 167static int 168gpiolib_request(struct gpio_chip *chip, unsigned int offset) 169{ 170 return BCM5301X_GPIO_FUNCNAME(gpio_request)(chip->base + offset, "gpiolib"); 171} 172 173static void 174gpiolib_free(struct gpio_chip *chip, unsigned int offset) 175{ 176 BCM5301X_GPIO_FUNCNAME(gpio_free)(chip->base + offset); 177} 178 179static int 180gpiolib_direction_input(struct gpio_chip *chip, unsigned int offset) 181{ 182 return BCM5301X_GPIO_FUNCNAME(gpio_direction_input)(chip->base + offset); 183} 184 185static int 186gpiolib_get_value(struct gpio_chip *chip, unsigned int offset) 187{ 188 return gpio_get_value(chip->base + offset); 189} 190 191static int 192gpiolib_direction_output(struct gpio_chip *chip, unsigned int offset, int value) 193{ 194 return BCM5301X_GPIO_FUNCNAME(gpio_direction_output)(chip->base + offset, value); 195} 196 197static void 198gpiolib_set_value(struct gpio_chip *chip, unsigned int offset, int value) 199{ 200 gpio_set_value(chip->base + offset, value); 201} 202 203static struct gpio_chip gc = { 204 .label = "bcm5301x_gpio", 205 .owner = THIS_MODULE, 206 .request = gpiolib_request, 207 .free = gpiolib_free, 208 .direction_input = gpiolib_direction_input, 209 .get = gpiolib_get_value, 210 .direction_output = gpiolib_direction_output, 211 .set = gpiolib_set_value, 212 .base = 0, 213 .ngpio = ARCH_NR_GPIOS, 214}; 215#endif /* CONFIG_GPIOLIB */ 216 217static int 218gen_gpio_init(void) 219{ 220 221#ifdef CONFIG_GPIOLIB 222 gpiochip_add(&gc); 223#endif 224 225 return 0; 226} 227 228static void 229gen_gpio_exit(void) 230{ 231#ifdef CONFIG_GPIOLIB 232 (void)gpiochip_remove(&gc); 233#endif 234 235} 236 237module_init(gen_gpio_init); 238module_exit(gen_gpio_exit); 239