blob: 804c300759604db5dacfacf5ab4f17c9d12be330 [file] [log] [blame]
Uwe Kleine-König689f2a02007-09-30 20:35:09 +01001/*
2 * arch/arm/mach-ns9xxx/gpio.c
3 *
Uwe Kleine-König724ce5e2008-02-15 08:41:06 +01004 * Copyright (C) 2006,2007 by Digi International Inc.
Uwe Kleine-König689f2a02007-09-30 20:35:09 +01005 * 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/compiler.h>
12#include <linux/init.h>
13#include <linux/spinlock.h>
14#include <linux/module.h>
15
Russell Kinga09e64f2008-08-05 16:14:15 +010016#include <mach/gpio.h>
17#include <mach/processor.h>
18#include <mach/processor-ns9360.h>
Uwe Kleine-König689f2a02007-09-30 20:35:09 +010019#include <asm/bug.h>
20#include <asm/types.h>
21#include <asm/bitops.h>
22
Uwe Kleine-König724ce5e2008-02-15 08:41:06 +010023#include "gpio-ns9360.h"
24
Uwe Kleine-König689f2a02007-09-30 20:35:09 +010025#if defined(CONFIG_PROCESSOR_NS9360)
26#define GPIO_MAX 72
27#elif defined(CONFIG_PROCESSOR_NS9750)
28#define GPIO_MAX 49
29#endif
30
31/* protects BBU_GCONFx and BBU_GCTRLx */
32static spinlock_t gpio_lock = __SPIN_LOCK_UNLOCKED(gpio_lock);
33
34/* only access gpiores with atomic ops */
Uwe Kleine-Königac5bbf22008-03-06 16:21:42 +010035static DECLARE_BITMAP(gpiores, GPIO_MAX + 1);
Uwe Kleine-König689f2a02007-09-30 20:35:09 +010036
37static inline int ns9xxx_valid_gpio(unsigned gpio)
38{
39#if defined(CONFIG_PROCESSOR_NS9360)
40 if (processor_is_ns9360())
41 return gpio <= 72;
42 else
43#endif
44#if defined(CONFIG_PROCESSOR_NS9750)
45 if (processor_is_ns9750())
46 return gpio <= 49;
47 else
48#endif
Uwe Kleine-König724ce5e2008-02-15 08:41:06 +010049 {
Uwe Kleine-König689f2a02007-09-30 20:35:09 +010050 BUG();
Uwe Kleine-König724ce5e2008-02-15 08:41:06 +010051 return 0;
52 }
Uwe Kleine-König689f2a02007-09-30 20:35:09 +010053}
54
55int gpio_request(unsigned gpio, const char *label)
56{
57 if (likely(ns9xxx_valid_gpio(gpio)))
58 return test_and_set_bit(gpio, gpiores) ? -EBUSY : 0;
59 else
60 return -EINVAL;
61}
62EXPORT_SYMBOL(gpio_request);
63
64void gpio_free(unsigned gpio)
65{
66 clear_bit(gpio, gpiores);
67 return;
68}
69EXPORT_SYMBOL(gpio_free);
70
Uwe Kleine-König689f2a02007-09-30 20:35:09 +010071int gpio_direction_input(unsigned gpio)
72{
73 if (likely(ns9xxx_valid_gpio(gpio))) {
Uwe Kleine-König724ce5e2008-02-15 08:41:06 +010074 int ret = -EINVAL;
75 unsigned long flags;
76
77 spin_lock_irqsave(&gpio_lock, flags);
78#if defined(CONFIG_PROCESSOR_NS9360)
79 if (processor_is_ns9360())
80 ret = __ns9360_gpio_configure(gpio, 0, 0, 3);
81 else
82#endif
83 BUG();
84
85 spin_unlock_irqrestore(&gpio_lock, flags);
86
87 return ret;
88
Uwe Kleine-König689f2a02007-09-30 20:35:09 +010089 } else
90 return -EINVAL;
91}
92EXPORT_SYMBOL(gpio_direction_input);
93
94int gpio_direction_output(unsigned gpio, int value)
95{
96 if (likely(ns9xxx_valid_gpio(gpio))) {
Uwe Kleine-König724ce5e2008-02-15 08:41:06 +010097 int ret = -EINVAL;
98 unsigned long flags;
99
Uwe Kleine-König689f2a02007-09-30 20:35:09 +0100100 gpio_set_value(gpio, value);
101
Uwe Kleine-König724ce5e2008-02-15 08:41:06 +0100102 spin_lock_irqsave(&gpio_lock, flags);
103#if defined(CONFIG_PROCESSOR_NS9360)
104 if (processor_is_ns9360())
105 ret = __ns9360_gpio_configure(gpio, 1, 0, 3);
106 else
107#endif
108 BUG();
109
110 spin_unlock_irqrestore(&gpio_lock, flags);
111
112 return ret;
Uwe Kleine-König689f2a02007-09-30 20:35:09 +0100113 } else
114 return -EINVAL;
115}
116EXPORT_SYMBOL(gpio_direction_output);
117
118int gpio_get_value(unsigned gpio)
119{
Uwe Kleine-König724ce5e2008-02-15 08:41:06 +0100120#if defined(CONFIG_PROCESSOR_NS9360)
121 if (processor_is_ns9360())
122 return ns9360_gpio_get_value(gpio);
123 else
124#endif
125 {
126 BUG();
127 return -EINVAL;
128 }
Uwe Kleine-König689f2a02007-09-30 20:35:09 +0100129}
130EXPORT_SYMBOL(gpio_get_value);
131
132void gpio_set_value(unsigned gpio, int value)
133{
Uwe Kleine-König689f2a02007-09-30 20:35:09 +0100134 unsigned long flags;
Uwe Kleine-König689f2a02007-09-30 20:35:09 +0100135 spin_lock_irqsave(&gpio_lock, flags);
Uwe Kleine-König724ce5e2008-02-15 08:41:06 +0100136#if defined(CONFIG_PROCESSOR_NS9360)
137 if (processor_is_ns9360())
138 ns9360_gpio_set_value(gpio, value);
Uwe Kleine-König689f2a02007-09-30 20:35:09 +0100139 else
Uwe Kleine-König724ce5e2008-02-15 08:41:06 +0100140#endif
141 BUG();
Uwe Kleine-König689f2a02007-09-30 20:35:09 +0100142
143 spin_unlock_irqrestore(&gpio_lock, flags);
144}
145EXPORT_SYMBOL(gpio_set_value);