]> git.openfabrics.org - ~shefty/rdma-dev.git/blob - drivers/gpio/cs5535-gpio.c
79eb9c5a2923df4d88fe08643151c0078cf8ed6a
[~shefty/rdma-dev.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 errata_outl(struct cs5535_gpio_chip *chip, u32 val,
60                 unsigned int reg)
61 {
62         unsigned long addr = chip->base + 0x80 + reg;
63
64         /*
65          * According to the CS5536 errata (#36), after suspend
66          * a write to the high bank GPIO register will clear all
67          * non-selected bits; the recommended workaround is a
68          * read-modify-write operation.
69          *
70          * Don't apply this errata to the edge status GPIOs, as writing
71          * to their lower bits will clear them.
72          */
73         if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS)
74                 val |= inl(addr);
75         outl(val, addr);
76 }
77
78 static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
79                 unsigned int reg)
80 {
81         if (offset < 16)
82                 /* low bank register */
83                 outl(1 << offset, chip->base + reg);
84         else
85                 /* high bank register */
86                 errata_outl(chip, 1 << (offset - 16), reg);
87 }
88
89 void cs5535_gpio_set(unsigned offset, unsigned int reg)
90 {
91         struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
92         unsigned long flags;
93
94         spin_lock_irqsave(&chip->lock, flags);
95         __cs5535_gpio_set(chip, offset, reg);
96         spin_unlock_irqrestore(&chip->lock, flags);
97 }
98 EXPORT_SYMBOL_GPL(cs5535_gpio_set);
99
100 static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
101                 unsigned int reg)
102 {
103         if (offset < 16)
104                 /* low bank register */
105                 outl(1 << (offset + 16), chip->base + reg);
106         else
107                 /* high bank register */
108                 errata_outl(chip, 1 << offset, reg);
109 }
110
111 void cs5535_gpio_clear(unsigned offset, unsigned int reg)
112 {
113         struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
114         unsigned long flags;
115
116         spin_lock_irqsave(&chip->lock, flags);
117         __cs5535_gpio_clear(chip, offset, reg);
118         spin_unlock_irqrestore(&chip->lock, flags);
119 }
120 EXPORT_SYMBOL_GPL(cs5535_gpio_clear);
121
122 int cs5535_gpio_isset(unsigned offset, unsigned int reg)
123 {
124         struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
125         unsigned long flags;
126         long val;
127
128         spin_lock_irqsave(&chip->lock, flags);
129         if (offset < 16)
130                 /* low bank register */
131                 val = inl(chip->base + reg);
132         else {
133                 /* high bank register */
134                 val = inl(chip->base + 0x80 + reg);
135                 offset -= 16;
136         }
137         spin_unlock_irqrestore(&chip->lock, flags);
138
139         return (val & (1 << offset)) ? 1 : 0;
140 }
141 EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
142
143 /*
144  * Generic gpio_chip API support.
145  */
146
147 static int chip_gpio_request(struct gpio_chip *c, unsigned offset)
148 {
149         struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
150         unsigned long flags;
151
152         spin_lock_irqsave(&chip->lock, flags);
153
154         /* check if this pin is available */
155         if ((mask & (1 << offset)) == 0) {
156                 dev_info(&chip->pdev->dev,
157                         "pin %u is not available (check mask)\n", offset);
158                 spin_unlock_irqrestore(&chip->lock, flags);
159                 return -EINVAL;
160         }
161
162         /* disable output aux 1 & 2 on this pin */
163         __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1);
164         __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2);
165
166         /* disable input aux 1 on this pin */
167         __cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1);
168
169         spin_unlock_irqrestore(&chip->lock, flags);
170
171         return 0;
172 }
173
174 static int chip_gpio_get(struct gpio_chip *chip, unsigned offset)
175 {
176         return cs5535_gpio_isset(offset, GPIO_READ_BACK);
177 }
178
179 static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
180 {
181         if (val)
182                 cs5535_gpio_set(offset, GPIO_OUTPUT_VAL);
183         else
184                 cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL);
185 }
186
187 static int chip_direction_input(struct gpio_chip *c, unsigned offset)
188 {
189         struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
190         unsigned long flags;
191
192         spin_lock_irqsave(&chip->lock, flags);
193         __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
194         __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE);
195         spin_unlock_irqrestore(&chip->lock, flags);
196
197         return 0;
198 }
199
200 static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
201 {
202         struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
203         unsigned long flags;
204
205         spin_lock_irqsave(&chip->lock, flags);
206
207         __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
208         __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE);
209         if (val)
210                 __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL);
211         else
212                 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL);
213
214         spin_unlock_irqrestore(&chip->lock, flags);
215
216         return 0;
217 }
218
219 static const char * const cs5535_gpio_names[] = {
220         "GPIO0", "GPIO1", "GPIO2", "GPIO3",
221         "GPIO4", "GPIO5", "GPIO6", "GPIO7",
222         "GPIO8", "GPIO9", "GPIO10", "GPIO11",
223         "GPIO12", "GPIO13", "GPIO14", "GPIO15",
224         "GPIO16", "GPIO17", "GPIO18", "GPIO19",
225         "GPIO20", "GPIO21", "GPIO22", NULL,
226         "GPIO24", "GPIO25", "GPIO26", "GPIO27",
227         "GPIO28", NULL, NULL, NULL,
228 };
229
230 static struct cs5535_gpio_chip cs5535_gpio_chip = {
231         .chip = {
232                 .owner = THIS_MODULE,
233                 .label = DRV_NAME,
234
235                 .base = 0,
236                 .ngpio = 32,
237                 .names = cs5535_gpio_names,
238                 .request = chip_gpio_request,
239
240                 .get = chip_gpio_get,
241                 .set = chip_gpio_set,
242
243                 .direction_input = chip_direction_input,
244                 .direction_output = chip_direction_output,
245         },
246 };
247
248 static int __init cs5535_gpio_probe(struct pci_dev *pdev,
249                 const struct pci_device_id *pci_id)
250 {
251         int err;
252         ulong mask_orig = mask;
253
254         /* There are two ways to get the GPIO base address; one is by
255          * fetching it from MSR_LBAR_GPIO, the other is by reading the
256          * PCI BAR info.  The latter method is easier (especially across
257          * different architectures), so we'll stick with that for now.  If
258          * it turns out to be unreliable in the face of crappy BIOSes, we
259          * can always go back to using MSRs.. */
260
261         err = pci_enable_device_io(pdev);
262         if (err) {
263                 dev_err(&pdev->dev, "can't enable device IO\n");
264                 goto done;
265         }
266
267         err = pci_request_region(pdev, GPIO_BAR, DRV_NAME);
268         if (err) {
269                 dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR);
270                 goto done;
271         }
272
273         /* set up the driver-specific struct */
274         cs5535_gpio_chip.base = pci_resource_start(pdev, GPIO_BAR);
275         cs5535_gpio_chip.pdev = pdev;
276         spin_lock_init(&cs5535_gpio_chip.lock);
277
278         dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", GPIO_BAR,
279                         (unsigned long long) cs5535_gpio_chip.base);
280
281         /* mask out reserved pins */
282         mask &= 0x1F7FFFFF;
283
284         /* do not allow pin 28, Power Button, as there's special handling
285          * in the PMC needed. (note 12, p. 48) */
286         mask &= ~(1 << 28);
287
288         if (mask_orig != mask)
289                 dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n",
290                                 mask_orig, mask);
291
292         /* finally, register with the generic GPIO API */
293         err = gpiochip_add(&cs5535_gpio_chip.chip);
294         if (err)
295                 goto release_region;
296
297         dev_info(&pdev->dev, DRV_NAME ": GPIO support successfully loaded.\n");
298         return 0;
299
300 release_region:
301         pci_release_region(pdev, GPIO_BAR);
302 done:
303         return err;
304 }
305
306 static void __exit cs5535_gpio_remove(struct pci_dev *pdev)
307 {
308         int err;
309
310         err = gpiochip_remove(&cs5535_gpio_chip.chip);
311         if (err) {
312                 /* uhh? */
313                 dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
314         }
315         pci_release_region(pdev, GPIO_BAR);
316 }
317
318 static struct pci_device_id cs5535_gpio_pci_tbl[] = {
319         { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_ISA) },
320         { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) },
321         { 0, },
322 };
323 MODULE_DEVICE_TABLE(pci, cs5535_gpio_pci_tbl);
324
325 /*
326  * We can't use the standard PCI driver registration stuff here, since
327  * that allows only one driver to bind to each PCI device (and we want
328  * multiple drivers to be able to bind to the device).  Instead, manually
329  * scan for the PCI device, request a single region, and keep track of the
330  * devices that we're using.
331  */
332
333 static int __init cs5535_gpio_scan_pci(void)
334 {
335         struct pci_dev *pdev;
336         int err = -ENODEV;
337         int i;
338
339         for (i = 0; i < ARRAY_SIZE(cs5535_gpio_pci_tbl); i++) {
340                 pdev = pci_get_device(cs5535_gpio_pci_tbl[i].vendor,
341                                 cs5535_gpio_pci_tbl[i].device, NULL);
342                 if (pdev) {
343                         err = cs5535_gpio_probe(pdev, &cs5535_gpio_pci_tbl[i]);
344                         if (err)
345                                 pci_dev_put(pdev);
346
347                         /* we only support a single CS5535/6 southbridge */
348                         break;
349                 }
350         }
351
352         return err;
353 }
354
355 static void __exit cs5535_gpio_free_pci(void)
356 {
357         cs5535_gpio_remove(cs5535_gpio_chip.pdev);
358         pci_dev_put(cs5535_gpio_chip.pdev);
359 }
360
361 static int __init cs5535_gpio_init(void)
362 {
363         return cs5535_gpio_scan_pci();
364 }
365
366 static void __exit cs5535_gpio_exit(void)
367 {
368         cs5535_gpio_free_pci();
369 }
370
371 module_init(cs5535_gpio_init);
372 module_exit(cs5535_gpio_exit);
373
374 MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
375 MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
376 MODULE_LICENSE("GPL");