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(u32 val, unsigned long addr)
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.
71 static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
75 /* low bank register */
76 outl(1 << offset, chip->base + reg);
78 /* high bank register */
79 errata_outl(1 << (offset - 16), chip->base + 0x80 + reg);
82 void cs5535_gpio_set(unsigned offset, unsigned int reg)
84 struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
87 spin_lock_irqsave(&chip->lock, flags);
88 __cs5535_gpio_set(chip, offset, reg);
89 spin_unlock_irqrestore(&chip->lock, flags);
91 EXPORT_SYMBOL_GPL(cs5535_gpio_set);
93 static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
97 /* low bank register */
98 outl(1 << (offset + 16), chip->base + reg);
100 /* high bank register */
101 errata_outl(1 << offset, chip->base + 0x80 + reg);
104 void cs5535_gpio_clear(unsigned offset, unsigned int reg)
106 struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
109 spin_lock_irqsave(&chip->lock, flags);
110 __cs5535_gpio_clear(chip, offset, reg);
111 spin_unlock_irqrestore(&chip->lock, flags);
113 EXPORT_SYMBOL_GPL(cs5535_gpio_clear);
115 int cs5535_gpio_isset(unsigned offset, unsigned int reg)
117 struct cs5535_gpio_chip *chip = &cs5535_gpio_chip;
121 spin_lock_irqsave(&chip->lock, flags);
123 /* low bank register */
124 val = inl(chip->base + reg);
126 /* high bank register */
127 val = inl(chip->base + 0x80 + reg);
130 spin_unlock_irqrestore(&chip->lock, flags);
132 return (val & (1 << offset)) ? 1 : 0;
134 EXPORT_SYMBOL_GPL(cs5535_gpio_isset);
137 * Generic gpio_chip API support.
140 static int chip_gpio_request(struct gpio_chip *c, unsigned offset)
142 struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
145 spin_lock_irqsave(&chip->lock, flags);
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);
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);
159 /* disable input aux 1 on this pin */
160 __cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1);
162 spin_unlock_irqrestore(&chip->lock, flags);
167 static int chip_gpio_get(struct gpio_chip *chip, unsigned offset)
169 return cs5535_gpio_isset(offset, GPIO_READ_BACK);
172 static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
175 cs5535_gpio_set(offset, GPIO_OUTPUT_VAL);
177 cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL);
180 static int chip_direction_input(struct gpio_chip *c, unsigned offset)
182 struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
185 spin_lock_irqsave(&chip->lock, flags);
186 __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
187 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE);
188 spin_unlock_irqrestore(&chip->lock, flags);
193 static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
195 struct cs5535_gpio_chip *chip = (struct cs5535_gpio_chip *) c;
198 spin_lock_irqsave(&chip->lock, flags);
200 __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
201 __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE);
203 __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL);
205 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL);
207 spin_unlock_irqrestore(&chip->lock, flags);
212 static const char * const cs5535_gpio_names[] = {
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,
223 static struct cs5535_gpio_chip cs5535_gpio_chip = {
225 .owner = THIS_MODULE,
230 .names = cs5535_gpio_names,
231 .request = chip_gpio_request,
233 .get = chip_gpio_get,
234 .set = chip_gpio_set,
236 .direction_input = chip_direction_input,
237 .direction_output = chip_direction_output,
241 static int __init cs5535_gpio_probe(struct pci_dev *pdev,
242 const struct pci_device_id *pci_id)
245 ulong mask_orig = mask;
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.. */
254 err = pci_enable_device_io(pdev);
256 dev_err(&pdev->dev, "can't enable device IO\n");
260 err = pci_request_region(pdev, GPIO_BAR, DRV_NAME);
262 dev_err(&pdev->dev, "can't alloc PCI BAR #%d\n", GPIO_BAR);
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);
271 dev_info(&pdev->dev, "allocated PCI BAR #%d: base 0x%llx\n", GPIO_BAR,
272 (unsigned long long) cs5535_gpio_chip.base);
274 /* mask out reserved pins */
277 /* do not allow pin 28, Power Button, as there's special handling
278 * in the PMC needed. (note 12, p. 48) */
281 if (mask_orig != mask)
282 dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n",
285 /* finally, register with the generic GPIO API */
286 err = gpiochip_add(&cs5535_gpio_chip.chip);
290 dev_info(&pdev->dev, DRV_NAME ": GPIO support successfully loaded.\n");
294 pci_release_region(pdev, GPIO_BAR);
299 static void __exit cs5535_gpio_remove(struct pci_dev *pdev)
303 err = gpiochip_remove(&cs5535_gpio_chip.chip);
306 dev_err(&pdev->dev, "unable to remove gpio_chip?\n");
308 pci_release_region(pdev, GPIO_BAR);
311 static 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) },
316 MODULE_DEVICE_TABLE(pci, cs5535_gpio_pci_tbl);
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.
326 static int __init cs5535_gpio_scan_pci(void)
328 struct pci_dev *pdev;
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);
336 err = cs5535_gpio_probe(pdev, &cs5535_gpio_pci_tbl[i]);
340 /* we only support a single CS5535/6 southbridge */
348 static void __exit cs5535_gpio_free_pci(void)
350 cs5535_gpio_remove(cs5535_gpio_chip.pdev);
351 pci_dev_put(cs5535_gpio_chip.pdev);
354 static int __init cs5535_gpio_init(void)
356 return cs5535_gpio_scan_pci();
359 static void __exit cs5535_gpio_exit(void)
361 cs5535_gpio_free_pci();
364 module_init(cs5535_gpio_init);
365 module_exit(cs5535_gpio_exit);
367 MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>");
368 MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver");
369 MODULE_LICENSE("GPL");