Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/ath79/gpio.c
10820 views
1
/*
2
* Atheros AR71XX/AR724X/AR913X GPIO API support
3
*
4
* Copyright (C) 2008-2010 Gabor Juhos <[email protected]>
5
* Copyright (C) 2008 Imre Kaloz <[email protected]>
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-ath79/ar71xx_regs.h>
22
#include <asm/mach-ath79/ath79.h>
23
#include "common.h"
24
25
static void __iomem *ath79_gpio_base;
26
static unsigned long ath79_gpio_count;
27
static DEFINE_SPINLOCK(ath79_gpio_lock);
28
29
static void __ath79_gpio_set_value(unsigned gpio, int value)
30
{
31
void __iomem *base = ath79_gpio_base;
32
33
if (value)
34
__raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
35
else
36
__raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
37
}
38
39
static int __ath79_gpio_get_value(unsigned gpio)
40
{
41
return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
42
}
43
44
static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
45
{
46
return __ath79_gpio_get_value(offset);
47
}
48
49
static void ath79_gpio_set_value(struct gpio_chip *chip,
50
unsigned offset, int value)
51
{
52
__ath79_gpio_set_value(offset, value);
53
}
54
55
static int ath79_gpio_direction_input(struct gpio_chip *chip,
56
unsigned offset)
57
{
58
void __iomem *base = ath79_gpio_base;
59
unsigned long flags;
60
61
spin_lock_irqsave(&ath79_gpio_lock, flags);
62
63
__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
64
base + AR71XX_GPIO_REG_OE);
65
66
spin_unlock_irqrestore(&ath79_gpio_lock, flags);
67
68
return 0;
69
}
70
71
static int ath79_gpio_direction_output(struct gpio_chip *chip,
72
unsigned offset, int value)
73
{
74
void __iomem *base = ath79_gpio_base;
75
unsigned long flags;
76
77
spin_lock_irqsave(&ath79_gpio_lock, flags);
78
79
if (value)
80
__raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
81
else
82
__raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
83
84
__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
85
base + AR71XX_GPIO_REG_OE);
86
87
spin_unlock_irqrestore(&ath79_gpio_lock, flags);
88
89
return 0;
90
}
91
92
static struct gpio_chip ath79_gpio_chip = {
93
.label = "ath79",
94
.get = ath79_gpio_get_value,
95
.set = ath79_gpio_set_value,
96
.direction_input = ath79_gpio_direction_input,
97
.direction_output = ath79_gpio_direction_output,
98
.base = 0,
99
};
100
101
void ath79_gpio_function_enable(u32 mask)
102
{
103
void __iomem *base = ath79_gpio_base;
104
unsigned long flags;
105
106
spin_lock_irqsave(&ath79_gpio_lock, flags);
107
108
__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) | mask,
109
base + AR71XX_GPIO_REG_FUNC);
110
/* flush write */
111
__raw_readl(base + AR71XX_GPIO_REG_FUNC);
112
113
spin_unlock_irqrestore(&ath79_gpio_lock, flags);
114
}
115
116
void ath79_gpio_function_disable(u32 mask)
117
{
118
void __iomem *base = ath79_gpio_base;
119
unsigned long flags;
120
121
spin_lock_irqsave(&ath79_gpio_lock, flags);
122
123
__raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~mask,
124
base + AR71XX_GPIO_REG_FUNC);
125
/* flush write */
126
__raw_readl(base + AR71XX_GPIO_REG_FUNC);
127
128
spin_unlock_irqrestore(&ath79_gpio_lock, flags);
129
}
130
131
void ath79_gpio_function_setup(u32 set, u32 clear)
132
{
133
void __iomem *base = ath79_gpio_base;
134
unsigned long flags;
135
136
spin_lock_irqsave(&ath79_gpio_lock, flags);
137
138
__raw_writel((__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~clear) | set,
139
base + AR71XX_GPIO_REG_FUNC);
140
/* flush write */
141
__raw_readl(base + AR71XX_GPIO_REG_FUNC);
142
143
spin_unlock_irqrestore(&ath79_gpio_lock, flags);
144
}
145
146
void __init ath79_gpio_init(void)
147
{
148
int err;
149
150
if (soc_is_ar71xx())
151
ath79_gpio_count = AR71XX_GPIO_COUNT;
152
else if (soc_is_ar724x())
153
ath79_gpio_count = AR724X_GPIO_COUNT;
154
else if (soc_is_ar913x())
155
ath79_gpio_count = AR913X_GPIO_COUNT;
156
else
157
BUG();
158
159
ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE);
160
ath79_gpio_chip.ngpio = ath79_gpio_count;
161
162
err = gpiochip_add(&ath79_gpio_chip);
163
if (err)
164
panic("cannot add AR71xx GPIO chip, error=%d", err);
165
}
166
167
int gpio_get_value(unsigned gpio)
168
{
169
if (gpio < ath79_gpio_count)
170
return __ath79_gpio_get_value(gpio);
171
172
return __gpio_get_value(gpio);
173
}
174
EXPORT_SYMBOL(gpio_get_value);
175
176
void gpio_set_value(unsigned gpio, int value)
177
{
178
if (gpio < ath79_gpio_count)
179
__ath79_gpio_set_value(gpio, value);
180
else
181
__gpio_set_value(gpio, value);
182
}
183
EXPORT_SYMBOL(gpio_set_value);
184
185
int gpio_to_irq(unsigned gpio)
186
{
187
/* FIXME */
188
return -EINVAL;
189
}
190
EXPORT_SYMBOL(gpio_to_irq);
191
192
int irq_to_gpio(unsigned irq)
193
{
194
/* FIXME */
195
return -EINVAL;
196
}
197
EXPORT_SYMBOL(irq_to_gpio);
198
199