• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/arm/plat-brcm/
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