Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/gpio/rdc321x-gpio.c
15109 views
1
/*
2
* RDC321x GPIO driver
3
*
4
* Copyright (C) 2008, Volker Weiss <[email protected]>
5
* Copyright (C) 2007-2010 Florian Fainelli <[email protected]>
6
*
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
11
*
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
16
*
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
*
21
*/
22
#include <linux/module.h>
23
#include <linux/kernel.h>
24
#include <linux/init.h>
25
#include <linux/spinlock.h>
26
#include <linux/platform_device.h>
27
#include <linux/pci.h>
28
#include <linux/gpio.h>
29
#include <linux/mfd/rdc321x.h>
30
#include <linux/slab.h>
31
32
struct rdc321x_gpio {
33
spinlock_t lock;
34
struct pci_dev *sb_pdev;
35
u32 data_reg[2];
36
int reg1_ctrl_base;
37
int reg1_data_base;
38
int reg2_ctrl_base;
39
int reg2_data_base;
40
struct gpio_chip chip;
41
};
42
43
/* read GPIO pin */
44
static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio)
45
{
46
struct rdc321x_gpio *gpch;
47
u32 value = 0;
48
int reg;
49
50
gpch = container_of(chip, struct rdc321x_gpio, chip);
51
reg = gpio < 32 ? gpch->reg1_data_base : gpch->reg2_data_base;
52
53
spin_lock(&gpch->lock);
54
pci_write_config_dword(gpch->sb_pdev, reg,
55
gpch->data_reg[gpio < 32 ? 0 : 1]);
56
pci_read_config_dword(gpch->sb_pdev, reg, &value);
57
spin_unlock(&gpch->lock);
58
59
return (1 << (gpio & 0x1f)) & value ? 1 : 0;
60
}
61
62
static void rdc_gpio_set_value_impl(struct gpio_chip *chip,
63
unsigned gpio, int value)
64
{
65
struct rdc321x_gpio *gpch;
66
int reg = (gpio < 32) ? 0 : 1;
67
68
gpch = container_of(chip, struct rdc321x_gpio, chip);
69
70
if (value)
71
gpch->data_reg[reg] |= 1 << (gpio & 0x1f);
72
else
73
gpch->data_reg[reg] &= ~(1 << (gpio & 0x1f));
74
75
pci_write_config_dword(gpch->sb_pdev,
76
reg ? gpch->reg2_data_base : gpch->reg1_data_base,
77
gpch->data_reg[reg]);
78
}
79
80
/* set GPIO pin to value */
81
static void rdc_gpio_set_value(struct gpio_chip *chip,
82
unsigned gpio, int value)
83
{
84
struct rdc321x_gpio *gpch;
85
86
gpch = container_of(chip, struct rdc321x_gpio, chip);
87
spin_lock(&gpch->lock);
88
rdc_gpio_set_value_impl(chip, gpio, value);
89
spin_unlock(&gpch->lock);
90
}
91
92
static int rdc_gpio_config(struct gpio_chip *chip,
93
unsigned gpio, int value)
94
{
95
struct rdc321x_gpio *gpch;
96
int err;
97
u32 reg;
98
99
gpch = container_of(chip, struct rdc321x_gpio, chip);
100
101
spin_lock(&gpch->lock);
102
err = pci_read_config_dword(gpch->sb_pdev, gpio < 32 ?
103
gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, &reg);
104
if (err)
105
goto unlock;
106
107
reg |= 1 << (gpio & 0x1f);
108
109
err = pci_write_config_dword(gpch->sb_pdev, gpio < 32 ?
110
gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, reg);
111
if (err)
112
goto unlock;
113
114
rdc_gpio_set_value_impl(chip, gpio, value);
115
116
unlock:
117
spin_unlock(&gpch->lock);
118
119
return err;
120
}
121
122
/* configure GPIO pin as input */
123
static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
124
{
125
return rdc_gpio_config(chip, gpio, 1);
126
}
127
128
/*
129
* Cache the initial value of both GPIO data registers
130
*/
131
static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
132
{
133
int err;
134
struct resource *r;
135
struct rdc321x_gpio *rdc321x_gpio_dev;
136
struct rdc321x_gpio_pdata *pdata;
137
138
pdata = pdev->dev.platform_data;
139
if (!pdata) {
140
dev_err(&pdev->dev, "no platform data supplied\n");
141
return -ENODEV;
142
}
143
144
rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL);
145
if (!rdc321x_gpio_dev) {
146
dev_err(&pdev->dev, "failed to allocate private data\n");
147
return -ENOMEM;
148
}
149
150
r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1");
151
if (!r) {
152
dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n");
153
err = -ENODEV;
154
goto out_free;
155
}
156
157
spin_lock_init(&rdc321x_gpio_dev->lock);
158
rdc321x_gpio_dev->sb_pdev = pdata->sb_pdev;
159
rdc321x_gpio_dev->reg1_ctrl_base = r->start;
160
rdc321x_gpio_dev->reg1_data_base = r->start + 0x4;
161
162
r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2");
163
if (!r) {
164
dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n");
165
err = -ENODEV;
166
goto out_free;
167
}
168
169
rdc321x_gpio_dev->reg2_ctrl_base = r->start;
170
rdc321x_gpio_dev->reg2_data_base = r->start + 0x4;
171
172
rdc321x_gpio_dev->chip.label = "rdc321x-gpio";
173
rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input;
174
rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config;
175
rdc321x_gpio_dev->chip.get = rdc_gpio_get_value;
176
rdc321x_gpio_dev->chip.set = rdc_gpio_set_value;
177
rdc321x_gpio_dev->chip.base = 0;
178
rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios;
179
180
platform_set_drvdata(pdev, rdc321x_gpio_dev);
181
182
/* This might not be, what others (BIOS, bootloader, etc.)
183
wrote to these registers before, but it's a good guess. Still
184
better than just using 0xffffffff. */
185
err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
186
rdc321x_gpio_dev->reg1_data_base,
187
&rdc321x_gpio_dev->data_reg[0]);
188
if (err)
189
goto out_drvdata;
190
191
err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev,
192
rdc321x_gpio_dev->reg2_data_base,
193
&rdc321x_gpio_dev->data_reg[1]);
194
if (err)
195
goto out_drvdata;
196
197
dev_info(&pdev->dev, "registering %d GPIOs\n",
198
rdc321x_gpio_dev->chip.ngpio);
199
return gpiochip_add(&rdc321x_gpio_dev->chip);
200
201
out_drvdata:
202
platform_set_drvdata(pdev, NULL);
203
out_free:
204
kfree(rdc321x_gpio_dev);
205
return err;
206
}
207
208
static int __devexit rdc321x_gpio_remove(struct platform_device *pdev)
209
{
210
int ret;
211
struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev);
212
213
ret = gpiochip_remove(&rdc321x_gpio_dev->chip);
214
if (ret)
215
dev_err(&pdev->dev, "failed to unregister chip\n");
216
217
kfree(rdc321x_gpio_dev);
218
platform_set_drvdata(pdev, NULL);
219
220
return ret;
221
}
222
223
static struct platform_driver rdc321x_gpio_driver = {
224
.driver.name = "rdc321x-gpio",
225
.driver.owner = THIS_MODULE,
226
.probe = rdc321x_gpio_probe,
227
.remove = __devexit_p(rdc321x_gpio_remove),
228
};
229
230
static int __init rdc321x_gpio_init(void)
231
{
232
return platform_driver_register(&rdc321x_gpio_driver);
233
}
234
235
static void __exit rdc321x_gpio_exit(void)
236
{
237
platform_driver_unregister(&rdc321x_gpio_driver);
238
}
239
240
module_init(rdc321x_gpio_init);
241
module_exit(rdc321x_gpio_exit);
242
243
MODULE_AUTHOR("Florian Fainelli <[email protected]>");
244
MODULE_DESCRIPTION("RDC321x GPIO driver");
245
MODULE_LICENSE("GPL");
246
MODULE_ALIAS("platform:rdc321x-gpio");
247
248