Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mips/ar7/gpio.c
10817 views
1
/*
2
* Copyright (C) 2007 Felix Fietkau <[email protected]>
3
* Copyright (C) 2007 Eugene Konev <[email protected]>
4
* Copyright (C) 2009-2010 Florian Fainelli <[email protected]>
5
*
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
*/
20
21
#include <linux/module.h>
22
#include <linux/gpio.h>
23
24
#include <asm/mach-ar7/gpio.h>
25
26
struct ar7_gpio_chip {
27
void __iomem *regs;
28
struct gpio_chip chip;
29
};
30
31
static int ar7_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
32
{
33
struct ar7_gpio_chip *gpch =
34
container_of(chip, struct ar7_gpio_chip, chip);
35
void __iomem *gpio_in = gpch->regs + AR7_GPIO_INPUT;
36
37
return readl(gpio_in) & (1 << gpio);
38
}
39
40
static int titan_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
41
{
42
struct ar7_gpio_chip *gpch =
43
container_of(chip, struct ar7_gpio_chip, chip);
44
void __iomem *gpio_in0 = gpch->regs + TITAN_GPIO_INPUT_0;
45
void __iomem *gpio_in1 = gpch->regs + TITAN_GPIO_INPUT_1;
46
47
return readl(gpio >> 5 ? gpio_in1 : gpio_in0) & (1 << (gpio & 0x1f));
48
}
49
50
static void ar7_gpio_set_value(struct gpio_chip *chip,
51
unsigned gpio, int value)
52
{
53
struct ar7_gpio_chip *gpch =
54
container_of(chip, struct ar7_gpio_chip, chip);
55
void __iomem *gpio_out = gpch->regs + AR7_GPIO_OUTPUT;
56
unsigned tmp;
57
58
tmp = readl(gpio_out) & ~(1 << gpio);
59
if (value)
60
tmp |= 1 << gpio;
61
writel(tmp, gpio_out);
62
}
63
64
static void titan_gpio_set_value(struct gpio_chip *chip,
65
unsigned gpio, int value)
66
{
67
struct ar7_gpio_chip *gpch =
68
container_of(chip, struct ar7_gpio_chip, chip);
69
void __iomem *gpio_out0 = gpch->regs + TITAN_GPIO_OUTPUT_0;
70
void __iomem *gpio_out1 = gpch->regs + TITAN_GPIO_OUTPUT_1;
71
unsigned tmp;
72
73
tmp = readl(gpio >> 5 ? gpio_out1 : gpio_out0) & ~(1 << (gpio & 0x1f));
74
if (value)
75
tmp |= 1 << (gpio & 0x1f);
76
writel(tmp, gpio >> 5 ? gpio_out1 : gpio_out0);
77
}
78
79
static int ar7_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
80
{
81
struct ar7_gpio_chip *gpch =
82
container_of(chip, struct ar7_gpio_chip, chip);
83
void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
84
85
writel(readl(gpio_dir) | (1 << gpio), gpio_dir);
86
87
return 0;
88
}
89
90
static int titan_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
91
{
92
struct ar7_gpio_chip *gpch =
93
container_of(chip, struct ar7_gpio_chip, chip);
94
void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
95
void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
96
97
if (gpio >= TITAN_GPIO_MAX)
98
return -EINVAL;
99
100
writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) | (1 << (gpio & 0x1f)),
101
gpio >> 5 ? gpio_dir1 : gpio_dir0);
102
return 0;
103
}
104
105
static int ar7_gpio_direction_output(struct gpio_chip *chip,
106
unsigned gpio, int value)
107
{
108
struct ar7_gpio_chip *gpch =
109
container_of(chip, struct ar7_gpio_chip, chip);
110
void __iomem *gpio_dir = gpch->regs + AR7_GPIO_DIR;
111
112
ar7_gpio_set_value(chip, gpio, value);
113
writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir);
114
115
return 0;
116
}
117
118
static int titan_gpio_direction_output(struct gpio_chip *chip,
119
unsigned gpio, int value)
120
{
121
struct ar7_gpio_chip *gpch =
122
container_of(chip, struct ar7_gpio_chip, chip);
123
void __iomem *gpio_dir0 = gpch->regs + TITAN_GPIO_DIR_0;
124
void __iomem *gpio_dir1 = gpch->regs + TITAN_GPIO_DIR_1;
125
126
if (gpio >= TITAN_GPIO_MAX)
127
return -EINVAL;
128
129
titan_gpio_set_value(chip, gpio, value);
130
writel(readl(gpio >> 5 ? gpio_dir1 : gpio_dir0) & ~(1 <<
131
(gpio & 0x1f)), gpio >> 5 ? gpio_dir1 : gpio_dir0);
132
133
return 0;
134
}
135
136
static struct ar7_gpio_chip ar7_gpio_chip = {
137
.chip = {
138
.label = "ar7-gpio",
139
.direction_input = ar7_gpio_direction_input,
140
.direction_output = ar7_gpio_direction_output,
141
.set = ar7_gpio_set_value,
142
.get = ar7_gpio_get_value,
143
.base = 0,
144
.ngpio = AR7_GPIO_MAX,
145
}
146
};
147
148
static struct ar7_gpio_chip titan_gpio_chip = {
149
.chip = {
150
.label = "titan-gpio",
151
.direction_input = titan_gpio_direction_input,
152
.direction_output = titan_gpio_direction_output,
153
.set = titan_gpio_set_value,
154
.get = titan_gpio_get_value,
155
.base = 0,
156
.ngpio = TITAN_GPIO_MAX,
157
}
158
};
159
160
static inline int ar7_gpio_enable_ar7(unsigned gpio)
161
{
162
void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
163
164
writel(readl(gpio_en) | (1 << gpio), gpio_en);
165
166
return 0;
167
}
168
169
static inline int ar7_gpio_enable_titan(unsigned gpio)
170
{
171
void __iomem *gpio_en0 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_0;
172
void __iomem *gpio_en1 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_1;
173
174
writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) | (1 << (gpio & 0x1f)),
175
gpio >> 5 ? gpio_en1 : gpio_en0);
176
177
return 0;
178
}
179
180
int ar7_gpio_enable(unsigned gpio)
181
{
182
return ar7_is_titan() ? ar7_gpio_enable_titan(gpio) :
183
ar7_gpio_enable_ar7(gpio);
184
}
185
EXPORT_SYMBOL(ar7_gpio_enable);
186
187
static inline int ar7_gpio_disable_ar7(unsigned gpio)
188
{
189
void __iomem *gpio_en = ar7_gpio_chip.regs + AR7_GPIO_ENABLE;
190
191
writel(readl(gpio_en) & ~(1 << gpio), gpio_en);
192
193
return 0;
194
}
195
196
static inline int ar7_gpio_disable_titan(unsigned gpio)
197
{
198
void __iomem *gpio_en0 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_0;
199
void __iomem *gpio_en1 = titan_gpio_chip.regs + TITAN_GPIO_ENBL_1;
200
201
writel(readl(gpio >> 5 ? gpio_en1 : gpio_en0) & ~(1 << (gpio & 0x1f)),
202
gpio >> 5 ? gpio_en1 : gpio_en0);
203
204
return 0;
205
}
206
207
int ar7_gpio_disable(unsigned gpio)
208
{
209
return ar7_is_titan() ? ar7_gpio_disable_titan(gpio) :
210
ar7_gpio_disable_ar7(gpio);
211
}
212
EXPORT_SYMBOL(ar7_gpio_disable);
213
214
struct titan_gpio_cfg {
215
u32 reg;
216
u32 shift;
217
u32 func;
218
};
219
220
static struct titan_gpio_cfg titan_gpio_table[] = {
221
/* reg, start bit, mux value */
222
{4, 24, 1},
223
{4, 26, 1},
224
{4, 28, 1},
225
{4, 30, 1},
226
{5, 6, 1},
227
{5, 8, 1},
228
{5, 10, 1},
229
{5, 12, 1},
230
{7, 14, 3},
231
{7, 16, 3},
232
{7, 18, 3},
233
{7, 20, 3},
234
{7, 22, 3},
235
{7, 26, 3},
236
{7, 28, 3},
237
{7, 30, 3},
238
{8, 0, 3},
239
{8, 2, 3},
240
{8, 4, 3},
241
{8, 10, 3},
242
{8, 14, 3},
243
{8, 16, 3},
244
{8, 18, 3},
245
{8, 20, 3},
246
{9, 8, 3},
247
{9, 10, 3},
248
{9, 12, 3},
249
{9, 14, 3},
250
{9, 18, 3},
251
{9, 20, 3},
252
{9, 24, 3},
253
{9, 26, 3},
254
{9, 28, 3},
255
{9, 30, 3},
256
{10, 0, 3},
257
{10, 2, 3},
258
{10, 8, 3},
259
{10, 10, 3},
260
{10, 12, 3},
261
{10, 14, 3},
262
{13, 12, 3},
263
{13, 14, 3},
264
{13, 16, 3},
265
{13, 18, 3},
266
{13, 24, 3},
267
{13, 26, 3},
268
{13, 28, 3},
269
{13, 30, 3},
270
{14, 2, 3},
271
{14, 6, 3},
272
{14, 8, 3},
273
{14, 12, 3}
274
};
275
276
static int titan_gpio_pinsel(unsigned gpio)
277
{
278
struct titan_gpio_cfg gpio_cfg;
279
u32 mux_status, pin_sel_reg, tmp;
280
void __iomem *pin_sel = (void __iomem *)KSEG1ADDR(AR7_REGS_PINSEL);
281
282
if (gpio >= ARRAY_SIZE(titan_gpio_table))
283
return -EINVAL;
284
285
gpio_cfg = titan_gpio_table[gpio];
286
pin_sel_reg = gpio_cfg.reg - 1;
287
288
mux_status = (readl(pin_sel + pin_sel_reg) >> gpio_cfg.shift) & 0x3;
289
290
/* Check the mux status */
291
if (!((mux_status == 0) || (mux_status == gpio_cfg.func)))
292
return 0;
293
294
/* Set the pin sel value */
295
tmp = readl(pin_sel + pin_sel_reg);
296
tmp |= ((gpio_cfg.func & 0x3) << gpio_cfg.shift);
297
writel(tmp, pin_sel + pin_sel_reg);
298
299
return 0;
300
}
301
302
/* Perform minimal Titan GPIO configuration */
303
static void titan_gpio_init(void)
304
{
305
unsigned i;
306
307
for (i = 44; i < 48; i++) {
308
titan_gpio_pinsel(i);
309
ar7_gpio_enable_titan(i);
310
titan_gpio_direction_input(&titan_gpio_chip.chip, i);
311
}
312
}
313
314
int __init ar7_gpio_init(void)
315
{
316
int ret;
317
struct ar7_gpio_chip *gpch;
318
unsigned size;
319
320
if (!ar7_is_titan()) {
321
gpch = &ar7_gpio_chip;
322
size = 0x10;
323
} else {
324
gpch = &titan_gpio_chip;
325
size = 0x1f;
326
}
327
328
gpch->regs = ioremap_nocache(AR7_REGS_GPIO, size);
329
if (!gpch->regs) {
330
printk(KERN_ERR "%s: failed to ioremap regs\n",
331
gpch->chip.label);
332
return -ENOMEM;
333
}
334
335
ret = gpiochip_add(&gpch->chip);
336
if (ret) {
337
printk(KERN_ERR "%s: failed to add gpiochip\n",
338
gpch->chip.label);
339
return ret;
340
}
341
printk(KERN_INFO "%s: registered %d GPIOs\n",
342
gpch->chip.label, gpch->chip.ngpio);
343
344
if (ar7_is_titan())
345
titan_gpio_init();
346
347
return ret;
348
}
349
350