blob: 496e97e4128caa42e5740a6e42606dada39d8e71 [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
Steve Mucklef132c6c2012-06-06 18:30:57 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/bitops.h>
15#include <linux/gpio.h>
16#include <linux/io.h>
17#include <linux/module.h>
18#include <mach/gpiomux.h>
19#include <mach/msm_iomap.h>
20
21/* see 80-VA736-2 Rev C pp 695-751
22**
23** These are actually the *shadow* gpio registers, since the
24** real ones (which allow full access) are only available to the
25** ARM9 side of the world.
26**
27** Since the _BASE need to be page-aligned when we're mapping them
28** to virtual addresses, adjust for the additional offset in these
29** macros.
30*/
31
32#if defined(CONFIG_ARCH_FSM9XXX)
33#define MSM_GPIO1_REG(off) (MSM_TLMM_BASE + (off))
34#endif
35
36#if defined(CONFIG_ARCH_FSM9XXX)
37
38/* output value */
39#define MSM_GPIO_OUT_G(group) MSM_GPIO1_REG(0x00 + (group) * 4)
40#define MSM_GPIO_OUT_N(gpio) MSM_GPIO_OUT_G((gpio) / 32)
41#define MSM_GPIO_OUT_0 MSM_GPIO_OUT_G(0) /* gpio 31-0 */
42#define MSM_GPIO_OUT_1 MSM_GPIO_OUT_G(1) /* gpio 63-32 */
43#define MSM_GPIO_OUT_2 MSM_GPIO_OUT_G(2) /* gpio 95-64 */
44#define MSM_GPIO_OUT_3 MSM_GPIO_OUT_G(3) /* gpio 127-96 */
45#define MSM_GPIO_OUT_4 MSM_GPIO_OUT_G(4) /* gpio 159-128 */
46#define MSM_GPIO_OUT_5 MSM_GPIO_OUT_G(5) /* gpio 167-160 */
47
48/* same pin map as above, output enable */
49#define MSM_GPIO_OE_G(group) MSM_GPIO1_REG(0x20 + (group) * 4)
50#define MSM_GPIO_OE_N(gpio) MSM_GPIO_OE_G((gpio) / 32)
51#define MSM_GPIO_OE_0 MSM_GPIO_OE_G(0)
52#define MSM_GPIO_OE_1 MSM_GPIO_OE_G(1)
53#define MSM_GPIO_OE_2 MSM_GPIO_OE_G(2)
54#define MSM_GPIO_OE_3 MSM_GPIO_OE_G(3)
55#define MSM_GPIO_OE_4 MSM_GPIO_OE_G(4)
56#define MSM_GPIO_OE_5 MSM_GPIO_OE_G(5)
57
58/* same pin map as above, input read */
59#define MSM_GPIO_IN_G(group) MSM_GPIO1_REG(0x48 + (group) * 4)
60#define MSM_GPIO_IN_N(gpio) MSM_GPIO_IN_G((gpio) / 32)
61#define MSM_GPIO_IN_0 MSM_GPIO_IN_G(0)
62#define MSM_GPIO_IN_1 MSM_GPIO_IN_G(1)
63#define MSM_GPIO_IN_2 MSM_GPIO_IN_G(2)
64#define MSM_GPIO_IN_3 MSM_GPIO_IN_G(3)
65#define MSM_GPIO_IN_4 MSM_GPIO_IN_G(4)
66#define MSM_GPIO_IN_5 MSM_GPIO_IN_G(5)
67
68/* configuration */
69#define MSM_GPIO_PAGE MSM_GPIO1_REG(0x40)
70#define MSM_GPIO_CONFIG MSM_GPIO1_REG(0x44)
71
72#endif /* CONFIG_ARCH_FSM9XXX */
73
74#define MSM_GPIO_BANK(bank, first, last) \
75 { \
76 .regs = { \
77 .out = MSM_GPIO_OUT_##bank, \
78 .in = MSM_GPIO_IN_##bank, \
79 .oe = MSM_GPIO_OE_##bank, \
80 }, \
81 .chip = { \
82 .base = (first), \
83 .ngpio = (last) - (first) + 1, \
84 .get = msm_gpio_get, \
85 .set = msm_gpio_set, \
86 .direction_input = msm_gpio_direction_input, \
87 .direction_output = msm_gpio_direction_output, \
88 .request = msm_gpio_request, \
89 .free = msm_gpio_free, \
90 } \
91 }
92
93struct msm_gpio_regs {
94 void __iomem *out;
95 void __iomem *in;
96 void __iomem *oe;
97};
98
99struct msm_gpio_chip {
100 spinlock_t lock;
101 struct gpio_chip chip;
102 struct msm_gpio_regs regs;
103};
104
105static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
106 unsigned offset, unsigned on)
107{
108 unsigned mask = BIT(offset);
109 unsigned val;
110
111 val = __raw_readl(msm_chip->regs.out);
112 if (on)
113 __raw_writel(val | mask, msm_chip->regs.out);
114 else
115 __raw_writel(val & ~mask, msm_chip->regs.out);
116 return 0;
117}
118
119static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
120{
121 struct msm_gpio_chip *msm_chip;
122 unsigned long irq_flags;
123
124 msm_chip = container_of(chip, struct msm_gpio_chip, chip);
125 spin_lock_irqsave(&msm_chip->lock, irq_flags);
126 __raw_writel(__raw_readl(msm_chip->regs.oe) & ~BIT(offset),
127 msm_chip->regs.oe);
128 spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
129 return 0;
130}
131
132static int
133msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
134{
135 struct msm_gpio_chip *msm_chip;
136 unsigned long irq_flags;
137
138 msm_chip = container_of(chip, struct msm_gpio_chip, chip);
139 spin_lock_irqsave(&msm_chip->lock, irq_flags);
140 msm_gpio_write(msm_chip, offset, value);
141 __raw_writel(__raw_readl(msm_chip->regs.oe) | BIT(offset),
142 msm_chip->regs.oe);
143 spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
144 return 0;
145}
146
147static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
148{
149 struct msm_gpio_chip *msm_chip;
150
151 msm_chip = container_of(chip, struct msm_gpio_chip, chip);
152 return (__raw_readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
153}
154
155static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
156{
157 struct msm_gpio_chip *msm_chip;
158 unsigned long irq_flags;
159
160 msm_chip = container_of(chip, struct msm_gpio_chip, chip);
161 spin_lock_irqsave(&msm_chip->lock, irq_flags);
162 msm_gpio_write(msm_chip, offset, value);
163 spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
164}
165
166#ifdef CONFIG_MSM_GPIOMUX
167static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
168{
169 return msm_gpiomux_get(chip->base + offset);
170}
171
172static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
173{
174 msm_gpiomux_put(chip->base + offset);
175}
176#else
177#define msm_gpio_request NULL
178#define msm_gpio_free NULL
179#endif
180
181struct msm_gpio_chip msm_gpio_chips[] = {
182 MSM_GPIO_BANK(0, 0, 31),
183 MSM_GPIO_BANK(1, 32, 63),
184 MSM_GPIO_BANK(2, 64, 95),
185 MSM_GPIO_BANK(3, 96, 127),
186 MSM_GPIO_BANK(4, 128, 159),
187 MSM_GPIO_BANK(5, 160, 167),
188};
189
190void msm_gpio_enter_sleep(int from_idle)
191{
192 return;
193}
194
195void msm_gpio_exit_sleep(void)
196{
197 return;
198}
199
200static int __init msm_init_gpio(void)
201{
202 int i;
203
204 for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
205 spin_lock_init(&msm_gpio_chips[i].lock);
206 gpiochip_add(&msm_gpio_chips[i].chip);
207 }
208
209 return 0;
210}
211
212postcore_initcall(msm_init_gpio);
213
214int gpio_tlmm_config(unsigned config, unsigned disable)
215{
216 uint32_t flags;
217 unsigned gpio = GPIO_PIN(config);
218
219 if (gpio > NR_MSM_GPIOS)
220 return -EINVAL;
221 flags = ((GPIO_DRVSTR(config) << 6) & (0x7 << 6)) |
222 ((GPIO_FUNC(config) << 2) & (0xf << 2)) |
223 ((GPIO_PULL(config) & 0x3));
224 dsb();
225 __raw_writel(gpio, MSM_GPIO_PAGE);
226 dsb();
227 __raw_writel(flags, MSM_GPIO_CONFIG);
228
229 return 0;
230}
231EXPORT_SYMBOL(gpio_tlmm_config);
232
233int msm_gpios_request_enable(const struct msm_gpio *table, int size)
234{
235 int rc = msm_gpios_request(table, size);
236 if (rc)
237 return rc;
238 rc = msm_gpios_enable(table, size);
239 if (rc)
240 msm_gpios_free(table, size);
241 return rc;
242}
243EXPORT_SYMBOL(msm_gpios_request_enable);
244
245void msm_gpios_disable_free(const struct msm_gpio *table, int size)
246{
247 msm_gpios_disable(table, size);
248 msm_gpios_free(table, size);
249}
250EXPORT_SYMBOL(msm_gpios_disable_free);
251
252int msm_gpios_request(const struct msm_gpio *table, int size)
253{
254 int rc;
255 int i;
256 const struct msm_gpio *g;
257 for (i = 0; i < size; i++) {
258 g = table + i;
259 rc = gpio_request(GPIO_PIN(g->gpio_cfg), g->label);
260 if (rc) {
261 pr_err("gpio_request(%d) <%s> failed: %d\n",
262 GPIO_PIN(g->gpio_cfg), g->label ?: "?", rc);
263 goto err;
264 }
265 }
266 return 0;
267err:
268 msm_gpios_free(table, i);
269 return rc;
270}
271EXPORT_SYMBOL(msm_gpios_request);
272
273void msm_gpios_free(const struct msm_gpio *table, int size)
274{
275 int i;
276 const struct msm_gpio *g;
277 for (i = size-1; i >= 0; i--) {
278 g = table + i;
279 gpio_free(GPIO_PIN(g->gpio_cfg));
280 }
281}
282EXPORT_SYMBOL(msm_gpios_free);
283
284int msm_gpios_enable(const struct msm_gpio *table, int size)
285{
286 int rc;
287 int i;
288 const struct msm_gpio *g;
289 for (i = 0; i < size; i++) {
290 g = table + i;
291 rc = gpio_tlmm_config(g->gpio_cfg, GPIO_CFG_ENABLE);
292 if (rc) {
293 pr_err("gpio_tlmm_config(0x%08x, GPIO_CFG_ENABLE)"
294 " <%s> failed: %d\n",
295 g->gpio_cfg, g->label ?: "?", rc);
296 pr_err("pin %d func %d dir %d pull %d drvstr %d\n",
297 GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
298 GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
299 GPIO_DRVSTR(g->gpio_cfg));
300 goto err;
301 }
302 }
303 return 0;
304err:
305 msm_gpios_disable(table, i);
306 return rc;
307}
308EXPORT_SYMBOL(msm_gpios_enable);
309
310int msm_gpios_disable(const struct msm_gpio *table, int size)
311{
312 int rc = 0;
313 int i;
314 const struct msm_gpio *g;
315 for (i = size-1; i >= 0; i--) {
316 int tmp;
317 g = table + i;
318 tmp = gpio_tlmm_config(g->gpio_cfg, GPIO_CFG_DISABLE);
319 if (tmp) {
320 pr_err("gpio_tlmm_config(0x%08x, GPIO_CFG_DISABLE)"
321 " <%s> failed: %d\n",
322 g->gpio_cfg, g->label ?: "?", rc);
323 pr_err("pin %d func %d dir %d pull %d drvstr %d\n",
324 GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
325 GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
326 GPIO_DRVSTR(g->gpio_cfg));
327 if (!rc)
328 rc = tmp;
329 }
330 }
331
332 return rc;
333}
334EXPORT_SYMBOL(msm_gpios_disable);
335