source: trunk/target/linux/ar71xx/files/arch/mips/ar71xx/gpio.c @ 28974

Last change on this file since 28974 was 28974, checked in by juhosg, 5 years ago

ar71xx: fix GPIO direction setup for AR934x

  • Property svn:eol-style set to native
File size: 5.5 KB
Line 
1/*
2 *  Atheros AR7XXX/AR9XXX SoC GPIO API support
3 *
4 *  Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
5 *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
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
9 *  by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/spinlock.h>
17#include <linux/io.h>
18#include <linux/ioport.h>
19#include <linux/gpio.h>
20
21#include <asm/mach-ar71xx/ar71xx.h>
22
23static DEFINE_SPINLOCK(ar71xx_gpio_lock);
24
25unsigned long ar71xx_gpio_count;
26EXPORT_SYMBOL(ar71xx_gpio_count);
27
28void __ar71xx_gpio_set_value(unsigned gpio, int value)
29{
30        void __iomem *base = ar71xx_gpio_base;
31
32        if (value)
33                __raw_writel(1 << gpio, base + GPIO_REG_SET);
34        else
35                __raw_writel(1 << gpio, base + GPIO_REG_CLEAR);
36}
37EXPORT_SYMBOL(__ar71xx_gpio_set_value);
38
39int __ar71xx_gpio_get_value(unsigned gpio)
40{
41        return (__raw_readl(ar71xx_gpio_base + GPIO_REG_IN) >> gpio) & 1;
42}
43EXPORT_SYMBOL(__ar71xx_gpio_get_value);
44
45static int ar71xx_gpio_get_value(struct gpio_chip *chip, unsigned offset)
46{
47        return __ar71xx_gpio_get_value(offset);
48}
49
50static void ar71xx_gpio_set_value(struct gpio_chip *chip,
51                                  unsigned offset, int value)
52{
53        __ar71xx_gpio_set_value(offset, value);
54}
55
56static int ar71xx_gpio_direction_input(struct gpio_chip *chip,
57                                       unsigned offset)
58{
59        void __iomem *base = ar71xx_gpio_base;
60        unsigned long flags;
61
62        spin_lock_irqsave(&ar71xx_gpio_lock, flags);
63
64        __raw_writel(__raw_readl(base + GPIO_REG_OE) & ~(1 << offset),
65                     base + GPIO_REG_OE);
66
67        spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
68
69        return 0;
70}
71
72static int ar71xx_gpio_direction_output(struct gpio_chip *chip,
73                                        unsigned offset, int value)
74{
75        void __iomem *base = ar71xx_gpio_base;
76        unsigned long flags;
77
78        spin_lock_irqsave(&ar71xx_gpio_lock, flags);
79
80        if (value)
81                __raw_writel(1 << offset, base + GPIO_REG_SET);
82        else
83                __raw_writel(1 << offset, base + GPIO_REG_CLEAR);
84
85        __raw_writel(__raw_readl(base + GPIO_REG_OE) | (1 << offset),
86                     base + GPIO_REG_OE);
87
88        spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
89
90        return 0;
91}
92
93static int ar934x_gpio_direction_input(struct gpio_chip *chip,
94                                       unsigned offset)
95{
96        void __iomem *base = ar71xx_gpio_base;
97        unsigned long flags;
98
99        spin_lock_irqsave(&ar71xx_gpio_lock, flags);
100
101        __raw_writel(__raw_readl(base + GPIO_REG_OE) | (1 << offset),
102                     base + GPIO_REG_OE);
103
104        spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
105
106        return 0;
107}
108
109static int ar934x_gpio_direction_output(struct gpio_chip *chip,
110                                        unsigned offset, int value)
111{
112        void __iomem *base = ar71xx_gpio_base;
113        unsigned long flags;
114
115        spin_lock_irqsave(&ar71xx_gpio_lock, flags);
116
117        if (value)
118                __raw_writel(1 << offset, base + GPIO_REG_SET);
119        else
120                __raw_writel(1 << offset, base + GPIO_REG_CLEAR);
121
122        __raw_writel(__raw_readl(base + GPIO_REG_OE) & ~(1 << offset),
123                     base + GPIO_REG_OE);
124
125        spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
126
127        return 0;
128}
129
130static struct gpio_chip ar71xx_gpio_chip = {
131        .label                  = "ar71xx",
132        .get                    = ar71xx_gpio_get_value,
133        .set                    = ar71xx_gpio_set_value,
134        .direction_input        = ar71xx_gpio_direction_input,
135        .direction_output       = ar71xx_gpio_direction_output,
136        .base                   = 0,
137        .ngpio                  = AR71XX_GPIO_COUNT,
138};
139
140void ar71xx_gpio_function_enable(u32 mask)
141{
142        void __iomem *base = ar71xx_gpio_base;
143        unsigned long flags;
144
145        spin_lock_irqsave(&ar71xx_gpio_lock, flags);
146
147        __raw_writel(__raw_readl(base + GPIO_REG_FUNC) | mask,
148                     base + GPIO_REG_FUNC);
149        /* flush write */
150        (void) __raw_readl(base + GPIO_REG_FUNC);
151
152        spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
153}
154
155void ar71xx_gpio_function_disable(u32 mask)
156{
157        void __iomem *base = ar71xx_gpio_base;
158        unsigned long flags;
159
160        spin_lock_irqsave(&ar71xx_gpio_lock, flags);
161
162        __raw_writel(__raw_readl(base + GPIO_REG_FUNC) & ~mask,
163                     base + GPIO_REG_FUNC);
164        /* flush write */
165        (void) __raw_readl(base + GPIO_REG_FUNC);
166
167        spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
168}
169
170void ar71xx_gpio_function_setup(u32 set, u32 clear)
171{
172        void __iomem *base = ar71xx_gpio_base;
173        unsigned long flags;
174
175        spin_lock_irqsave(&ar71xx_gpio_lock, flags);
176
177        __raw_writel((__raw_readl(base + GPIO_REG_FUNC) & ~clear) | set,
178                     base + GPIO_REG_FUNC);
179        /* flush write */
180        (void) __raw_readl(base + GPIO_REG_FUNC);
181
182        spin_unlock_irqrestore(&ar71xx_gpio_lock, flags);
183}
184EXPORT_SYMBOL(ar71xx_gpio_function_setup);
185
186void __init ar71xx_gpio_init(void)
187{
188        int err;
189
190        if (!request_mem_region(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
191                                "AR71xx GPIO controller"))
192                panic("cannot allocate AR71xx GPIO registers page");
193
194        switch (ar71xx_soc) {
195        case AR71XX_SOC_AR7130:
196        case AR71XX_SOC_AR7141:
197        case AR71XX_SOC_AR7161:
198                ar71xx_gpio_chip.ngpio = AR71XX_GPIO_COUNT;
199                break;
200
201        case AR71XX_SOC_AR7240:
202        case AR71XX_SOC_AR7241:
203        case AR71XX_SOC_AR7242:
204                ar71xx_gpio_chip.ngpio = AR724X_GPIO_COUNT;
205                break;
206
207        case AR71XX_SOC_AR9130:
208        case AR71XX_SOC_AR9132:
209                ar71xx_gpio_chip.ngpio = AR91XX_GPIO_COUNT;
210                break;
211
212        case AR71XX_SOC_AR9330:
213        case AR71XX_SOC_AR9331:
214                ar71xx_gpio_chip.ngpio = AR933X_GPIO_COUNT;
215                break;
216
217        case AR71XX_SOC_AR9341:
218        case AR71XX_SOC_AR9342:
219        case AR71XX_SOC_AR9344:
220                ar71xx_gpio_chip.ngpio = AR934X_GPIO_COUNT;
221                ar71xx_gpio_chip.direction_input = ar934x_gpio_direction_input;
222                ar71xx_gpio_chip.direction_output = ar934x_gpio_direction_output;
223                break;
224
225        default:
226                BUG();
227        }
228
229        err = gpiochip_add(&ar71xx_gpio_chip);
230        if (err)
231                panic("cannot add AR71xx GPIO chip, error=%d", err);
232}
Note: See TracBrowser for help on using the repository browser.