Commit | Line | Data |
---|---|---|
689f2a01 UKK |
1 | /* |
2 | * arch/arm/mach-ns9xxx/gpio.c | |
3 | * | |
724ce5ee | 4 | * Copyright (C) 2006,2007 by Digi International Inc. |
689f2a01 UKK |
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 | */ | |
9c656850 | 11 | #include <linux/kernel.h> |
689f2a01 UKK |
12 | #include <linux/compiler.h> |
13 | #include <linux/init.h> | |
14 | #include <linux/spinlock.h> | |
15 | #include <linux/module.h> | |
fbd3bdb2 | 16 | #include <linux/bitops.h> |
689f2a01 | 17 | |
a09e64fb RK |
18 | #include <mach/gpio.h> |
19 | #include <mach/processor.h> | |
20 | #include <mach/processor-ns9360.h> | |
689f2a01 UKK |
21 | #include <asm/bug.h> |
22 | #include <asm/types.h> | |
689f2a01 | 23 | |
724ce5ee UKK |
24 | #include "gpio-ns9360.h" |
25 | ||
689f2a01 UKK |
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 */ | |
33 | static spinlock_t gpio_lock = __SPIN_LOCK_UNLOCKED(gpio_lock); | |
34 | ||
35 | /* only access gpiores with atomic ops */ | |
ac5bbf21 | 36 | static DECLARE_BITMAP(gpiores, GPIO_MAX + 1); |
689f2a01 UKK |
37 | |
38 | static 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 | |
724ce5ee | 50 | { |
689f2a01 | 51 | BUG(); |
724ce5ee UKK |
52 | return 0; |
53 | } | |
689f2a01 UKK |
54 | } |
55 | ||
56 | int 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 | } | |
63 | EXPORT_SYMBOL(gpio_request); | |
64 | ||
65 | void gpio_free(unsigned gpio) | |
66 | { | |
9c656850 | 67 | might_sleep(); |
689f2a01 UKK |
68 | clear_bit(gpio, gpiores); |
69 | return; | |
70 | } | |
71 | EXPORT_SYMBOL(gpio_free); | |
72 | ||
724ce5ee | 73 | int gpio_direction_input(unsigned gpio) |
689f2a01 | 74 | { |
724ce5ee UKK |
75 | if (likely(ns9xxx_valid_gpio(gpio))) { |
76 | int ret = -EINVAL; | |
77 | unsigned long flags; | |
689f2a01 | 78 | |
724ce5ee UKK |
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(); | |
689f2a01 | 86 | |
724ce5ee | 87 | spin_unlock_irqrestore(&gpio_lock, flags); |
689f2a01 | 88 | |
724ce5ee | 89 | return ret; |
689f2a01 | 90 | |
689f2a01 UKK |
91 | } else |
92 | return -EINVAL; | |
93 | } | |
94 | EXPORT_SYMBOL(gpio_direction_input); | |
95 | ||
96 | int gpio_direction_output(unsigned gpio, int value) | |
97 | { | |
98 | if (likely(ns9xxx_valid_gpio(gpio))) { | |
724ce5ee UKK |
99 | int ret = -EINVAL; |
100 | unsigned long flags; | |
101 | ||
689f2a01 UKK |
102 | gpio_set_value(gpio, value); |
103 | ||
724ce5ee UKK |
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; | |
689f2a01 UKK |
115 | } else |
116 | return -EINVAL; | |
117 | } | |
118 | EXPORT_SYMBOL(gpio_direction_output); | |
119 | ||
120 | int gpio_get_value(unsigned gpio) | |
121 | { | |
724ce5ee UKK |
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 | } | |
689f2a01 UKK |
131 | } |
132 | EXPORT_SYMBOL(gpio_get_value); | |
133 | ||
134 | void gpio_set_value(unsigned gpio, int value) | |
135 | { | |
689f2a01 | 136 | unsigned long flags; |
689f2a01 | 137 | spin_lock_irqsave(&gpio_lock, flags); |
724ce5ee UKK |
138 | #if defined(CONFIG_PROCESSOR_NS9360) |
139 | if (processor_is_ns9360()) | |
140 | ns9360_gpio_set_value(gpio, value); | |
689f2a01 | 141 | else |
724ce5ee UKK |
142 | #endif |
143 | BUG(); | |
689f2a01 UKK |
144 | |
145 | spin_unlock_irqrestore(&gpio_lock, flags); | |
146 | } | |
147 | EXPORT_SYMBOL(gpio_set_value); |