Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-davinci/gpio-tnetv107x.c
10699 views
1
/*
2
* Texas Instruments TNETV107X GPIO Controller
3
*
4
* Copyright (C) 2010 Texas Instruments
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License as
8
* published by the Free Software Foundation version 2.
9
*
10
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
11
* kind, whether express or implied; without even the implied warranty
12
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*/
15
#include <linux/kernel.h>
16
#include <linux/init.h>
17
#include <linux/gpio.h>
18
19
#include <mach/common.h>
20
#include <mach/tnetv107x.h>
21
22
struct tnetv107x_gpio_regs {
23
u32 idver;
24
u32 data_in[3];
25
u32 data_out[3];
26
u32 direction[3];
27
u32 enable[3];
28
};
29
30
#define gpio_reg_index(gpio) ((gpio) >> 5)
31
#define gpio_reg_bit(gpio) BIT((gpio) & 0x1f)
32
33
#define gpio_reg_rmw(reg, mask, val) \
34
__raw_writel((__raw_readl(reg) & ~(mask)) | (val), (reg))
35
36
#define gpio_reg_set_bit(reg, gpio) \
37
gpio_reg_rmw((reg) + gpio_reg_index(gpio), 0, gpio_reg_bit(gpio))
38
39
#define gpio_reg_clear_bit(reg, gpio) \
40
gpio_reg_rmw((reg) + gpio_reg_index(gpio), gpio_reg_bit(gpio), 0)
41
42
#define gpio_reg_get_bit(reg, gpio) \
43
(__raw_readl((reg) + gpio_reg_index(gpio)) & gpio_reg_bit(gpio))
44
45
#define chip2controller(chip) \
46
container_of(chip, struct davinci_gpio_controller, chip)
47
48
#define TNETV107X_GPIO_CTLRS DIV_ROUND_UP(TNETV107X_N_GPIO, 32)
49
50
static struct davinci_gpio_controller chips[TNETV107X_GPIO_CTLRS];
51
52
static int tnetv107x_gpio_request(struct gpio_chip *chip, unsigned offset)
53
{
54
struct davinci_gpio_controller *ctlr = chip2controller(chip);
55
struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
56
unsigned gpio = chip->base + offset;
57
unsigned long flags;
58
59
spin_lock_irqsave(&ctlr->lock, flags);
60
61
gpio_reg_set_bit(regs->enable, gpio);
62
63
spin_unlock_irqrestore(&ctlr->lock, flags);
64
65
return 0;
66
}
67
68
static void tnetv107x_gpio_free(struct gpio_chip *chip, unsigned offset)
69
{
70
struct davinci_gpio_controller *ctlr = chip2controller(chip);
71
struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
72
unsigned gpio = chip->base + offset;
73
unsigned long flags;
74
75
spin_lock_irqsave(&ctlr->lock, flags);
76
77
gpio_reg_clear_bit(regs->enable, gpio);
78
79
spin_unlock_irqrestore(&ctlr->lock, flags);
80
}
81
82
static int tnetv107x_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
83
{
84
struct davinci_gpio_controller *ctlr = chip2controller(chip);
85
struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
86
unsigned gpio = chip->base + offset;
87
unsigned long flags;
88
89
spin_lock_irqsave(&ctlr->lock, flags);
90
91
gpio_reg_set_bit(regs->direction, gpio);
92
93
spin_unlock_irqrestore(&ctlr->lock, flags);
94
95
return 0;
96
}
97
98
static int tnetv107x_gpio_dir_out(struct gpio_chip *chip,
99
unsigned offset, int value)
100
{
101
struct davinci_gpio_controller *ctlr = chip2controller(chip);
102
struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
103
unsigned gpio = chip->base + offset;
104
unsigned long flags;
105
106
spin_lock_irqsave(&ctlr->lock, flags);
107
108
if (value)
109
gpio_reg_set_bit(regs->data_out, gpio);
110
else
111
gpio_reg_clear_bit(regs->data_out, gpio);
112
113
gpio_reg_clear_bit(regs->direction, gpio);
114
115
spin_unlock_irqrestore(&ctlr->lock, flags);
116
117
return 0;
118
}
119
120
static int tnetv107x_gpio_get(struct gpio_chip *chip, unsigned offset)
121
{
122
struct davinci_gpio_controller *ctlr = chip2controller(chip);
123
struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
124
unsigned gpio = chip->base + offset;
125
int ret;
126
127
ret = gpio_reg_get_bit(regs->data_in, gpio);
128
129
return ret ? 1 : 0;
130
}
131
132
static void tnetv107x_gpio_set(struct gpio_chip *chip,
133
unsigned offset, int value)
134
{
135
struct davinci_gpio_controller *ctlr = chip2controller(chip);
136
struct tnetv107x_gpio_regs __iomem *regs = ctlr->regs;
137
unsigned gpio = chip->base + offset;
138
unsigned long flags;
139
140
spin_lock_irqsave(&ctlr->lock, flags);
141
142
if (value)
143
gpio_reg_set_bit(regs->data_out, gpio);
144
else
145
gpio_reg_clear_bit(regs->data_out, gpio);
146
147
spin_unlock_irqrestore(&ctlr->lock, flags);
148
}
149
150
static int __init tnetv107x_gpio_setup(void)
151
{
152
int i, base;
153
unsigned ngpio;
154
struct davinci_soc_info *soc_info = &davinci_soc_info;
155
struct tnetv107x_gpio_regs *regs;
156
struct davinci_gpio_controller *ctlr;
157
158
if (soc_info->gpio_type != GPIO_TYPE_TNETV107X)
159
return 0;
160
161
ngpio = soc_info->gpio_num;
162
if (ngpio == 0) {
163
pr_err("GPIO setup: how many GPIOs?\n");
164
return -EINVAL;
165
}
166
167
if (WARN_ON(TNETV107X_N_GPIO < ngpio))
168
ngpio = TNETV107X_N_GPIO;
169
170
regs = ioremap(soc_info->gpio_base, SZ_4K);
171
if (WARN_ON(!regs))
172
return -EINVAL;
173
174
for (i = 0, base = 0; base < ngpio; i++, base += 32) {
175
ctlr = &chips[i];
176
177
ctlr->chip.label = "tnetv107x";
178
ctlr->chip.can_sleep = 0;
179
ctlr->chip.base = base;
180
ctlr->chip.ngpio = ngpio - base;
181
if (ctlr->chip.ngpio > 32)
182
ctlr->chip.ngpio = 32;
183
184
ctlr->chip.request = tnetv107x_gpio_request;
185
ctlr->chip.free = tnetv107x_gpio_free;
186
ctlr->chip.direction_input = tnetv107x_gpio_dir_in;
187
ctlr->chip.get = tnetv107x_gpio_get;
188
ctlr->chip.direction_output = tnetv107x_gpio_dir_out;
189
ctlr->chip.set = tnetv107x_gpio_set;
190
191
spin_lock_init(&ctlr->lock);
192
193
ctlr->regs = regs;
194
ctlr->set_data = &regs->data_out[i];
195
ctlr->clr_data = &regs->data_out[i];
196
ctlr->in_data = &regs->data_in[i];
197
198
gpiochip_add(&ctlr->chip);
199
}
200
201
soc_info->gpio_ctlrs = chips;
202
soc_info->gpio_ctlrs_num = DIV_ROUND_UP(ngpio, 32);
203
return 0;
204
}
205
pure_initcall(tnetv107x_gpio_setup);
206
207