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>
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.
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>
17 #include <linux/cs5535.h>
19 #define DRV_NAME "cs5535-gpio"
24 * 31-29,23 : reserved (always mask out)
36 * If a mask was not specified, allow all except
37 * reserved and Power Button
39 #define GPIO_DEFAULT_MASK 0x0F7FFFFF
41 static ulong mask
= GPIO_DEFAULT_MASK
;
42 module_param_named(mask
, mask
, ulong
, 0444);
43 MODULE_PARM_DESC(mask
, "GPIO channel mask.");
45 static struct cs5535_gpio_chip
{
46 struct gpio_chip chip
;
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.
59 static void errata_outl(struct cs5535_gpio_chip
*chip
, u32 val
,
62 unsigned long addr
= chip
->base
+ 0x80 + reg
;
64 if (reg
!= GPIO_POSITIVE_EDGE_STS
&& reg
!= GPIO_NEGATIVE_EDGE_STS
) {
66 val
|= (inl(addr
) & 0xffff); /* ignore the high bits */
68 val
|= (inl(addr
) ^ (val
>> 16));
73 static void __cs5535_gpio_set(struct cs5535_gpio_chip
*chip
, unsigned offset
,
77 /* low bank register */
78 outl(1 << offset
, chip
->base
+ reg
);
80 /* high bank register */
81 errata_outl(chip
, 1 << (offset
- 16), reg
);
84 void cs5535_gpio_set(unsigned offset
, unsigned int reg
)
86 struct cs5535_gpio_chip
*chip
= &cs5535_gpio_chip
;
89 spin_lock_irqsave(&chip
->lock
, flags
);
90 __cs5535_gpio_set(chip
, offset
, reg
);
91 spin_unlock_irqrestore(&chip
->lock
, flags
);
93 EXPORT_SYMBOL_GPL(cs5535_gpio_set
);
95 static void __cs5535_gpio_clear(struct cs5535_gpio_chip
*chip
, unsigned offset
,
99 /* low bank register */
100 outl(1 << (offset
+ 16), chip
->base
+ reg
);
102 /* high bank register */
103 errata_outl(chip
, 1 << offset
, reg
);
106 void cs5535_gpio_clear(unsigned offset
, unsigned int reg
)
108 struct cs5535_gpio_chip
*chip
= &cs5535_gpio_chip
;
111 spin_lock_irqsave(&chip
->lock
, flags
);
112 __cs5535_gpio_clear(chip
, offset
, reg
);
113 spin_unlock_irqrestore(&chip
->lock
, flags
);
115 EXPORT_SYMBOL_GPL(cs5535_gpio_clear
);
117 int cs5535_gpio_isset(unsigned offset
, unsigned int reg
)
119 struct cs5535_gpio_chip
*chip
= &cs5535_gpio_chip
;
123 spin_lock_irqsave(&chip
->lock
, flags
);
125 /* low bank register */
126 val
= inl(chip
->base
+ reg
);
128 /* high bank register */
129 val
= inl(chip
->base
+ 0x80 + reg
);
132 spin_unlock_irqrestore(&chip
->lock
, flags
);
134 return (val
& (1 << offset
)) ? 1 : 0;
136 EXPORT_SYMBOL_GPL(cs5535_gpio_isset
);
139 * Generic gpio_chip API support.
142 static int chip_gpio_request(struct gpio_chip
*c
, unsigned offset
)
144 struct cs5535_gpio_chip
*chip
= (struct cs5535_gpio_chip
*) c
;
147 spin_lock_irqsave(&chip
->lock
, flags
);
149 /* check if this pin is available */
150 if ((mask
& (1 << offset
)) == 0) {
151 dev_info(&chip
->pdev
->dev
,
152 "pin %u is not available (check mask)\n", offset
);
153 spin_unlock_irqrestore(&chip
->lock
, flags
);
157 /* disable output aux 1 & 2 on this pin */
158 __cs5535_gpio_clear(chip
, offset
, GPIO_OUTPUT_AUX1
);
159 __cs5535_gpio_clear(chip
, offset
, GPIO_OUTPUT_AUX2
);
161 /* disable input aux 1 on this pin */
162 __cs5535_gpio_clear(chip
, offset
, GPIO_INPUT_AUX1
);
164 spin_unlock_irqrestore(&chip
->lock
, flags
);
169 static int chip_gpio_get(struct gpio_chip
*chip
, unsigned offset
)
171 return cs5535_gpio_isset(offset
, GPIO_READ_BACK
);
174 static void chip_gpio_set(struct gpio_chip
*chip
, unsigned offset
, int val
)
177 cs5535_gpio_set(offset
, GPIO_OUTPUT_VAL
);
179 cs5535_gpio_clear(offset
, GPIO_OUTPUT_VAL
);
182 static int chip_direction_input(struct gpio_chip
*c
, unsigned offset
)
184 struct cs5535_gpio_chip
*chip
= (struct cs5535_gpio_chip
*) c
;
187 spin_lock_irqsave(&chip
->lock
, flags
);
188 __cs5535_gpio_set(chip
, offset
, GPIO_INPUT_ENABLE
);
189 __cs5535_gpio_clear(chip
, offset
, GPIO_OUTPUT_ENABLE
);
190 spin_unlock_irqrestore(&chip
->lock
, flags
);
195 static int chip_direction_output(struct gpio_chip
*c
, unsigned offset
, int val
)
197 struct cs5535_gpio_chip
*chip
= (struct cs5535_gpio_chip
*) c
;
200 spin_lock_irqsave(&chip
->lock
, flags
);
202 __cs5535_gpio_set(chip
, offset
, GPIO_INPUT_ENABLE
);
203 __cs5535_gpio_set(chip
, offset
, GPIO_OUTPUT_ENABLE
);
205 __cs5535_gpio_set(chip
, offset
, GPIO_OUTPUT_VAL
);
207 __cs5535_gpio_clear(chip
, offset
, GPIO_OUTPUT_VAL
);
209 spin_unlock_irqrestore(&chip
->lock
, flags
);
214 static const char * const cs5535_gpio_names
[] = {
215 "GPIO0", "GPIO1", "GPIO2", "GPIO3",
216 "GPIO4", "GPIO5", "GPIO6", "GPIO7",
217 "GPIO8", "GPIO9", "GPIO10", "GPIO11",
218 "GPIO12", "GPIO13", "GPIO14", "GPIO15",
219 "GPIO16", "GPIO17", "GPIO18", "GPIO19",
220 "GPIO20", "GPIO21", "GPIO22", NULL
,
221 "GPIO24", "GPIO25", "GPIO26", "GPIO27",
222 "GPIO28", NULL
, NULL
, NULL
,
225 static struct cs5535_gpio_chip cs5535_gpio_chip
= {
227 .owner
= THIS_MODULE
,
232 .names
= cs5535_gpio_names
,
233 .request
= chip_gpio_request
,
235 .get
= chip_gpio_get
,
236 .set
= chip_gpio_set
,
238 .direction_input
= chip_direction_input
,
239 .direction_output
= chip_direction_output
,
243 static int __init
cs5535_gpio_probe(struct pci_dev
*pdev
,
244 const struct pci_device_id
*pci_id
)
247 ulong mask_orig
= mask
;
249 /* There are two ways to get the GPIO base address; one is by
250 * fetching it from MSR_LBAR_GPIO, the other is by reading the
251 * PCI BAR info. The latter method is easier (especially across
252 * different architectures), so we'll stick with that for now. If
253 * it turns out to be unreliable in the face of crappy BIOSes, we
254 * can always go back to using MSRs.. */
256 err
= pci_enable_device_io(pdev
);
258 dev_err(&pdev
->dev
, "can't enable device IO\n");
262 err
= pci_request_region(pdev
, GPIO_BAR
, DRV_NAME
);
264 dev_err(&pdev
->dev
, "can't alloc PCI BAR #%d\n", GPIO_BAR
);
268 /* set up the driver-specific struct */
269 cs5535_gpio_chip
.base
= pci_resource_start(pdev
, GPIO_BAR
);
270 cs5535_gpio_chip
.pdev
= pdev
;
271 spin_lock_init(&cs5535_gpio_chip
.lock
);
273 dev_info(&pdev
->dev
, "allocated PCI BAR #%d: base 0x%llx\n", GPIO_BAR
,
274 (unsigned long long) cs5535_gpio_chip
.base
);
276 /* mask out reserved pins */
279 /* do not allow pin 28, Power Button, as there's special handling
280 * in the PMC needed. (note 12, p. 48) */
283 if (mask_orig
!= mask
)
284 dev_info(&pdev
->dev
, "mask changed from 0x%08lX to 0x%08lX\n",
287 /* finally, register with the generic GPIO API */
288 err
= gpiochip_add(&cs5535_gpio_chip
.chip
);
292 dev_info(&pdev
->dev
, DRV_NAME
": GPIO support successfully loaded.\n");
296 pci_release_region(pdev
, GPIO_BAR
);
301 static void __exit
cs5535_gpio_remove(struct pci_dev
*pdev
)
305 err
= gpiochip_remove(&cs5535_gpio_chip
.chip
);
308 dev_err(&pdev
->dev
, "unable to remove gpio_chip?\n");
310 pci_release_region(pdev
, GPIO_BAR
);
313 static struct pci_device_id cs5535_gpio_pci_tbl
[] = {
314 { PCI_DEVICE(PCI_VENDOR_ID_NS
, PCI_DEVICE_ID_NS_CS5535_ISA
) },
315 { PCI_DEVICE(PCI_VENDOR_ID_AMD
, PCI_DEVICE_ID_AMD_CS5536_ISA
) },
318 MODULE_DEVICE_TABLE(pci
, cs5535_gpio_pci_tbl
);
321 * We can't use the standard PCI driver registration stuff here, since
322 * that allows only one driver to bind to each PCI device (and we want
323 * multiple drivers to be able to bind to the device). Instead, manually
324 * scan for the PCI device, request a single region, and keep track of the
325 * devices that we're using.
328 static int __init
cs5535_gpio_scan_pci(void)
330 struct pci_dev
*pdev
;
334 for (i
= 0; i
< ARRAY_SIZE(cs5535_gpio_pci_tbl
); i
++) {
335 pdev
= pci_get_device(cs5535_gpio_pci_tbl
[i
].vendor
,
336 cs5535_gpio_pci_tbl
[i
].device
, NULL
);
338 err
= cs5535_gpio_probe(pdev
, &cs5535_gpio_pci_tbl
[i
]);
342 /* we only support a single CS5535/6 southbridge */
350 static void __exit
cs5535_gpio_free_pci(void)
352 cs5535_gpio_remove(cs5535_gpio_chip
.pdev
);
353 pci_dev_put(cs5535_gpio_chip
.pdev
);
356 static int __init
cs5535_gpio_init(void)
358 return cs5535_gpio_scan_pci();
361 static void __exit
cs5535_gpio_exit(void)
363 cs5535_gpio_free_pci();
366 module_init(cs5535_gpio_init
);
367 module_exit(cs5535_gpio_exit
);
369 MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
370 MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
371 MODULE_LICENSE("GPL");