Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / arch / arm / mach-ns9xxx / gpio.c
blob5286e9fc1d307bac62f1341dd6c4e728a83be33a
1 /*
2 * arch/arm/mach-ns9xxx/gpio.c
4 * Copyright (C) 2006 by Digi International Inc.
5 * All rights reserved.
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.
11 #include <linux/compiler.h>
12 #include <linux/init.h>
13 #include <linux/spinlock.h>
14 #include <linux/module.h>
16 #include <asm/arch-ns9xxx/gpio.h>
17 #include <asm/arch-ns9xxx/processor.h>
18 #include <asm/arch-ns9xxx/regs-bbu.h>
19 #include <asm/io.h>
20 #include <asm/bug.h>
21 #include <asm/types.h>
22 #include <asm/bitops.h>
24 #if defined(CONFIG_PROCESSOR_NS9360)
25 #define GPIO_MAX 72
26 #elif defined(CONFIG_PROCESSOR_NS9750)
27 #define GPIO_MAX 49
28 #endif
30 /* protects BBU_GCONFx and BBU_GCTRLx */
31 static spinlock_t gpio_lock = __SPIN_LOCK_UNLOCKED(gpio_lock);
33 /* only access gpiores with atomic ops */
34 static DECLARE_BITMAP(gpiores, GPIO_MAX + 1);
36 static inline int ns9xxx_valid_gpio(unsigned gpio)
38 #if defined(CONFIG_PROCESSOR_NS9360)
39 if (processor_is_ns9360())
40 return gpio <= 72;
41 else
42 #endif
43 #if defined(CONFIG_PROCESSOR_NS9750)
44 if (processor_is_ns9750())
45 return gpio <= 49;
46 else
47 #endif
48 BUG();
51 static inline void __iomem *ns9xxx_gpio_get_gconfaddr(unsigned gpio)
53 if (gpio < 56)
54 return BBU_GCONFb1(gpio / 8);
55 else
57 * this could be optimised away on
58 * ns9750 only builds, but it isn't ...
60 return BBU_GCONFb2((gpio - 56) / 8);
63 static inline void __iomem *ns9xxx_gpio_get_gctrladdr(unsigned gpio)
65 if (gpio < 32)
66 return BBU_GCTRL1;
67 else if (gpio < 64)
68 return BBU_GCTRL2;
69 else
70 /* this could be optimised away on ns9750 only builds */
71 return BBU_GCTRL3;
74 static inline void __iomem *ns9xxx_gpio_get_gstataddr(unsigned gpio)
76 if (gpio < 32)
77 return BBU_GSTAT1;
78 else if (gpio < 64)
79 return BBU_GSTAT2;
80 else
81 /* this could be optimised away on ns9750 only builds */
82 return BBU_GSTAT3;
85 int gpio_request(unsigned gpio, const char *label)
87 if (likely(ns9xxx_valid_gpio(gpio)))
88 return test_and_set_bit(gpio, gpiores) ? -EBUSY : 0;
89 else
90 return -EINVAL;
92 EXPORT_SYMBOL(gpio_request);
94 void gpio_free(unsigned gpio)
96 clear_bit(gpio, gpiores);
97 return;
99 EXPORT_SYMBOL(gpio_free);
102 * each gpio can serve for 4 different purposes [0..3]. These are called
103 * "functions" and passed in the parameter func. Functions 0-2 are always some
104 * special things, function 3 is GPIO. If func == 3 dir specifies input or
105 * output, and with inv you can enable an inverter (independent of func).
107 static int __ns9xxx_gpio_configure(unsigned gpio, int dir, int inv, int func)
109 void __iomem *conf = ns9xxx_gpio_get_gconfaddr(gpio);
110 u32 confval;
111 unsigned long flags;
113 spin_lock_irqsave(&gpio_lock, flags);
115 confval = __raw_readl(conf);
116 REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir);
117 REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv);
118 REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func);
119 __raw_writel(confval, conf);
121 spin_unlock_irqrestore(&gpio_lock, flags);
123 return 0;
126 int ns9xxx_gpio_configure(unsigned gpio, int inv, int func)
128 if (likely(ns9xxx_valid_gpio(gpio))) {
129 if (func == 3) {
130 printk(KERN_WARNING "use gpio_direction_input "
131 "or gpio_direction_output\n");
132 return -EINVAL;
133 } else
134 return __ns9xxx_gpio_configure(gpio, 0, inv, func);
135 } else
136 return -EINVAL;
138 EXPORT_SYMBOL(ns9xxx_gpio_configure);
140 int gpio_direction_input(unsigned gpio)
142 if (likely(ns9xxx_valid_gpio(gpio))) {
143 return __ns9xxx_gpio_configure(gpio, 0, 0, 3);
144 } else
145 return -EINVAL;
147 EXPORT_SYMBOL(gpio_direction_input);
149 int gpio_direction_output(unsigned gpio, int value)
151 if (likely(ns9xxx_valid_gpio(gpio))) {
152 gpio_set_value(gpio, value);
154 return __ns9xxx_gpio_configure(gpio, 1, 0, 3);
155 } else
156 return -EINVAL;
158 EXPORT_SYMBOL(gpio_direction_output);
160 int gpio_get_value(unsigned gpio)
162 void __iomem *stat = ns9xxx_gpio_get_gstataddr(gpio);
163 int ret;
165 ret = 1 & (__raw_readl(stat) >> (gpio & 31));
167 return ret;
169 EXPORT_SYMBOL(gpio_get_value);
171 void gpio_set_value(unsigned gpio, int value)
173 void __iomem *ctrl = ns9xxx_gpio_get_gctrladdr(gpio);
174 u32 ctrlval;
175 unsigned long flags;
177 spin_lock_irqsave(&gpio_lock, flags);
179 ctrlval = __raw_readl(ctrl);
181 if (value)
182 ctrlval |= 1 << (gpio & 31);
183 else
184 ctrlval &= ~(1 << (gpio & 31));
186 __raw_writel(ctrlval, ctrl);
188 spin_unlock_irqrestore(&gpio_lock, flags);
190 EXPORT_SYMBOL(gpio_set_value);