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