Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6.git] / drivers / gpio / cs5535-gpio.c
1 /*
2  * AMD CS5535/CS5536 GPIO driver
3  * Copyright (C) 2006  Advanced Micro Devices, Inc.
4  * Copyright (C) 2007-2009  Andres Salomon <dilinger@collabora.co.uk>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of version 2 of the GNU General Public License
8  * as published by the Free Software Foundation.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/spinlock.h>
13 #include <linux/module.h>
14 #include <linux/pci.h>
15 #include <linux/gpio.h>
16 #include <linux/io.h>
17 #include <linux/cs5535.h>
18
19 #define DRV_NAME "cs5535-gpio"
20 #define GPIO_BAR 1
21
22 /*
23  * Some GPIO pins
24  *  31-29,23 : reserved (always mask out)
25  *  28       : Power Button
26  *  26       : PME#
27  *  22-16    : LPC
28  *  14,15    : SMBus
29  *  9,8      : UART1
30  *  7        : PCI INTB
31  *  3,4      : UART2/DDC
32  *  2        : IDE_IRQ0
33  *  1        : AC_BEEP
34  *  0        : PCI INTA
35  *
36  * If a mask was not specified, allow all except
37  * reserved and Power Button
38  */
39 #define GPIO_DEFAULT_MASK 0x0F7FFFFF
40
41 static ulong mask = GPIO_DEFAULT_MASK;
42 module_param_named(mask, mask, ulong, 0444);
43 MODULE_PARM_DESC(mask, "GPIO channel mask.");
44
45 static struct cs5535_gpio_chip {
46         struct gpio_chip chip;
47         resource_size_t base;
48
49         struct pci_dev *pdev;
50         spinlock_t lock;
51 } cs5535_gpio_chip;
52
53 /*
54  * The CS5535/CS5536 GPIOs support a number of extra features not defined
55  * by the gpio_chip API, so these are exported.  For a full list of the
56  * registers, see include/linux/cs5535.h.
57  */
58
59 static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
60                 unsigned int reg)
61 {
62         if (offset < 16)
63                 /* low bank register */
64                 outl(1 << offset, chip->base + reg);
65         else
66                 /* high bank register */
67                 outl(1 << (offset - 16), chip->base + 0x80 + reg);
68 }
69
70 void cs5535_gpio_set(unsigned offset, unsigned int reg)
71 {
72         struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
73         unsigned long flags;
74
75         spin_lock_irqsave(&chip->lock, flags);
76         __cs5535_gpio_set(chip, offset, reg);
77         spin_unlock_irqrestore(&chip->lock, flags);
78 }
79 EXPORT_SYMBOL_GPL(cs5535_gpio_set);
80
81 static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
82                 unsigned int reg)
83 {
84         if (offset < 16)
85                 /* low bank register */
86                 outl(1 << (offset + 16), chip->base + reg);
87         else
88                 /* high bank register */
89                 outl(1 << offset, chip->base + 0x80 + reg);
90 }
91
92 void cs5535_gpio_clear(unsigned offset, unsigned int reg)
93 {
94         struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
95         unsigned long flags;
96
97         spin_lock_irqsave(&chip->lock, flags);
98         __cs5535_gpio_clear(chip, offset, reg);
99         spin_unlock_irqrestore(&chip->lock, flags);
100 }
101 EXPORT_SYMBOL_GPL(cs5535_gpio_clear);
102
103 int cs5535_gpio_isset(unsigned offset, unsigned int reg)
104 {
105         struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
106         unsigned long flags;
107         long val;
108
109         spin_lock_irqsave(&chip->lock, flags);
110         if (offset < 16)
111                 /* low bank register */
112                 val = inl(chip->base + reg);
113         else {
114                 /* high bank register */
115                 val = inl(chip->base + 0x80 + reg);
116                 offset -= 16;
117         }
118         spin_unlock_irqrestore(&chip->lock, flags);
119
120         return (val & (1 << offset)) ? 1 : 0;
121 }
122 EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
123
124 /*
125  * Generic gpio_chip API support.
126  */
127
128 static int chip_gpio_request(struct gpio_chip *c, unsigned offset)
129 {
130         struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
131         unsigned long flags;
132
133         spin_lock_irqsave(&chip->lock, flags);
134
135         /* check if this pin is available */
136         if ((mask & (1 << offset)) == 0) {
137                 dev_info(&chip->pdev->dev,
138                         "pin %u is not available (check mask)\n", offset);
139                 spin_unlock_irqrestore(&chip->lock, flags);
140                 return -EINVAL;
141         }
142
143         /* disable output aux 1 & 2 on this pin */
144         __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1);
145         __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2);
146
147         /* disable input aux 1 on this pin */
148         __cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1);
149
150         spin_unlock_irqrestore(&chip->lock, flags);
151
152         return 0;
153 }
154
155 static int chip_gpio_get(struct gpio_chip *chip, unsigned offset)
156 {
157         return cs5535_gpio_isset(offset, GPIO_OUTPUT_VAL);
158 }
159
160 static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
161 {
162         if (val)
163                 cs5535_gpio_set(offset, GPIO_OUTPUT_VAL);
164         else
165                 cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL);
166 }
167
168 static int chip_direction_input(struct gpio_chip *c, unsigned offset)
169 {
170         struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
171         unsigned long flags;
172
173         spin_lock_irqsave(&chip->lock, flags);
174         __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
175         spin_unlock_irqrestore(&chip->lock, flags);
176
177         return 0;
178 }
179
180 static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
181 {
182         struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
183         unsigned long flags;
184
185         spin_lock_irqsave(&chip->lock, flags);
186
187         __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE);
188         if (val)
189                 __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL);
190         else
191                 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL);
192
193         spin_unlock_irqrestore(&chip->lock, flags);
194
195         return 0;
196 }
197
198 static char *cs5535_gpio_names[] = {
199         "GPIO0", "GPIO1", "GPIO2", "GPIO3",
200         "GPIO4", "GPIO5", "GPIO6", "GPIO7",
201         "GPIO8", "GPIO9", "GPIO10", "GPIO11",
202         "GPIO12", "GPIO13", "GPIO14", "GPIO15",
203         "GPIO16", "GPIO17", "GPIO18", "GPIO19",
204         "GPIO20", "GPIO21", "GPIO22", NULL,
205         "GPIO24", "GPIO25", "GPIO26", "GPIO27",
206         "GPIO28", NULL, NULL, NULL,
207 };
208
209 static struct cs5535_gpio_chip cs5535_gpio_chip = {
210         .chip = {
211                 .owner = THIS_MODULE,
212                 .label = DRV_NAME,
213
214                 .base = 0,
215                 .ngpio = 32,
216                 .names = cs5535_gpio_names,
217                 .request = chip_gpio_request,
218
219                 .get = chip_gpio_get,
220                 .set = chip_gpio_set,
221
222                 .direction_input = chip_direction_input,
223                 .direction_output = chip_direction_output,
224         },
225 };
226
227 static int __init cs5535_gpio_probe(struct pci_dev *pdev,
228                 const struct pci_device_id *pci_id)
229 {
230         int err;
231         ulong mask_orig = mask;
232
233         /* There are two ways to get the GPIO base address; one is by
234          * fetching it from MSR_LBAR_GPIO, the other is by reading the
235          * PCI BAR info.  The latter method is easier (especially across
236          * different architectures), so we'll stick with that for now.  If
237          * it turns out to be unreliable in the face of crappy BIOSes, we
238          * can always go back to using MSRs.. */
239
240         err = pci_enable_device_io(pdev);
241         if (err) {
242                 dev_err(&pdev->dev, "can't enable device IO\n");
243                 goto done;
244         }
245
246         err = pci_request_region(pdev, GPIO_BAR, DRV_NAME);
247         if (err) {
248                 dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR);
249                 goto done;
250         }
251
252         /* set up the driver-specific struct */
253         cs5535_gpio_chip.base = pci_resource_start(pdev, GPIO_BAR);
254         cs5535_gpio_chip.pdev = pdev;
255         spin_lock_init(&cs5535_gpio_chip.lock);
256
257         dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", GPIO_BAR,
258                         (unsigned long long) cs5535_gpio_chip.base);
259
260         /* mask out reserved pins */
261         mask &= 0x1F7FFFFF;
262
263         /* do not allow pin 28, Power Button, as there's special handling
264          * in the PMC needed. (note 12, p. 48) */
265         mask &= ~(1 << 28);
266
267         if (mask_orig != mask)
268                 dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n",
269                                 mask_orig, mask);
270
271         /* finally, register with the generic GPIO API */
272         err = gpiochip_add(&cs5535_gpio_chip.chip);
273         if (err)
274                 goto release_region;
275
276         dev_info(&pdev->dev, DRV_NAME ": GPIO support successfully loaded.\n");
277         return 0;
278
279 release_region:
280         pci_release_region(pdev, GPIO_BAR);
281 done:
282         return err;
283 }
284
285 static void __exit cs5535_gpio_remove(struct pci_dev *pdev)
286 {
287         int err;
288
289         err = gpiochip_remove(&cs5535_gpio_chip.chip);
290         if (err) {
291                 /* uhh? */
292                 dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
293         }
294         pci_release_region(pdev, GPIO_BAR);
295 }
296
297 static struct pci_device_id cs5535_gpio_pci_tbl[] = {
298         { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
299         { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
300         { 0, },
301 };
302 MODULE_DEVICE_TABLE(pci, cs5535_gpio_pci_tbl);
303
304 /*
305  * We can't use the standard PCI driver registration stuff here, since
306  * that allows only one driver to bind to each PCI device (and we want
307  * multiple drivers to be able to bind to the device).  Instead, manually
308  * scan for the PCI device, request a single region, and keep track of the
309  * devices that we're using.
310  */
311
312 static int __init cs5535_gpio_scan_pci(void)
313 {
314         struct pci_dev *pdev;
315         int err = -ENODEV;
316         int i;
317
318         for (i = 0; i < ARRAY_SIZE(cs5535_gpio_pci_tbl); i++) {
319                 pdev = pci_get_device(cs5535_gpio_pci_tbl[i].vendor,
320                                 cs5535_gpio_pci_tbl[i].device, NULL);
321                 if (pdev) {
322                         err = cs5535_gpio_probe(pdev, &cs5535_gpio_pci_tbl[i]);
323                         if (err)
324                                 pci_dev_put(pdev);
325
326                         /* we only support a single CS5535/6 southbridge */
327                         break;
328                 }
329         }
330
331         return err;
332 }
333
334 static void __exit cs5535_gpio_free_pci(void)
335 {
336         cs5535_gpio_remove(cs5535_gpio_chip.pdev);
337         pci_dev_put(cs5535_gpio_chip.pdev);
338 }
339
340 static int __init cs5535_gpio_init(void)
341 {
342         return cs5535_gpio_scan_pci();
343 }
344
345 static void __exit cs5535_gpio_exit(void)
346 {
347         cs5535_gpio_free_pci();
348 }
349
350 module_init(cs5535_gpio_init);
351 module_exit(cs5535_gpio_exit);
352
353 MODULE_AUTHOR("Andres Salomon <dilinger@collabora.co.uk>");
354 MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
355 MODULE_LICENSE("GPL");